我真的很难理解Play的Iteratee
和Enumerator
的基本目的。
我读了
我阅读此answer来发现,它没有像
InputStream
那样依赖于拉模型,而是使用了推模型。迭代器是一种有趣的野兽-一方面,它将数据“推送”到处理程序,而不是依赖处理程序提取数据,因此具有更好的性能。另一方面,它允许处理程序控制何时应停止流。
但是后来Play关于
Iteratee
的文档说或更一般而言,使用
java.io.InputStream
枚举Enumerator.fromStream
。重要的是要注意,在应用此枚举器的迭代器准备接收更多输入之前,不会读取输入。等待....那是怎么回事?
数据是由
Enumerator
推送还是由Iteratee
提取? (即由谁来决定何时计算更多数据) 最佳答案
都。对于流的两端,它是完全不阻塞的。
在Enumerator
准备好接收数据之前,Iteratee
不会推送任何数据,直到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
状态,则可能需要花费更多时间才能提供进一步的输入。