Scala Play中的“枚举器”:推送还是拉取?

3
我真的很难理解 Play 的 Iteratees 和 Enumerators 的基本目的。
我已经阅读了:
- Normal Humans 理解 Play2 Iteratees - Iteratees - Enumerators 我阅读了这个答案,发现它不依赖于拉模型(如 InputStream),而是使用推模型。
迭代器是一个有趣的工具--一方面,它将数据“推送”到处理程序,而不是依赖于处理程序来拉取数据,因此具有更好的性能。另一方面,它允许处理程序控制何时停止流程。

但是Play关于Iteratee的文档说:

或者更一般地,使用Enumerator.fromStream枚举java.io.InputStream。需要注意的是,在应用此枚举器的Iteratee准备好接受更多输入之前,输入不会被读取。

等等....这是怎么回事?

数据由Enumerator推送还是由Iteratee拉取?(即谁决定何时计算更多数据)

1个回答

3

都可以。对于流的两端来说,它完全是非阻塞的。

EnumeratorIteratee准备好接收数据之前不会推送任何数据,并且在Iteratee发出准备好接收更多数据的信号之前不会再次推送任何数据。同时,Enumerator可以随意耗费时间来推送数据。两个过程都不会相互阻塞。

Iteratee中的这个方法是理解它如何工作的关键:

abstract def fold[B](folder: (Step[E, A]) ⇒ Future[B])(implicit ec: ExecutionContext): Future[B]

Iteratee中唯一必须实现的抽象方法。其余所有方法都是使用fold定义的。当Enumerator应用于Iteratee时,它会调用此方法,并提供folder,这实际上是一个回调。一旦Iteratee准备好了,它就会调用folder,并提供它当前所处的状态,如果可以接收更多数据,则为Cont,如果不需要任何更多数据,则为Done或者如果出现问题,则为Error。由于folder返回一个Future,因此如果Iteratee处于Cont状态,它可以花费尽可能长的时间来提供进一步的输入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接