为什么玩的PushEnumerator需要关闭()之前的迭代器将完成?(Why does Play&

2019-09-17 07:36发布

下面的例子,改编自游戏框架的文档:

val enumerateUsers: Enumerator[String] = {
  Enumerator("Guillaume", "Sadek", "Peter", "Erwan")
}
val consumeOne = Cont[String, String](in =>
  in match {
    case Input.EOF =>
      Done("", Input.Empty)
    case Input.Empty =>
      Done("", Input.Empty)
    case Input.El(s) =>
      Done(s, Input.Empty)
  })
println((enumerateUsers |>> consumeOne).flatMap(_.run).await.get)

打印出Guillaume

但是,如果我改变它,这样的EnumeratorPushEnumerator

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]()
// consumeOne as before
val i = enumerateUsers |>> consumeOne
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
println(i.flatMap(_.run).await.get)
// Timeout exception

我上iteratee的承诺超时异常。

为了得到它做和以前一样,我需要关闭PushEnumerator

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]()
// consumeOne as before
val i = enumerateUsers |>> consumeOne
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
enumerateUsers.close() // <-- magic line
println(i.flatMap(_.run).await.get)

而这种打印Guillaume如前。

我找不到,告诉我为什么,或语义差异是在这里什么文档。 可有人请点办法吗?

编辑 :我发现我的播放源的答案-它采取了一些狩猎:)我会纪念@ huynhjl的答案是正确的,因为他有点回答了这个问题,但我一直在寻找具体的答案是非常简单的。 播放实现使用副作用驱动插座,这是没有道理的 - 它只是不是我曾以为是什么(假设杀一切:d)。 里面play.core.server.netty.Helpers有一个叫函数socketOut[A](...) socketOut[A](...)具有功能调用step ,它返回一个Iteratee。 此Iteratee写入e当输入匹配的情况下到输出信道El(e) 。 我的假设是,Iteratees可以部分消耗枚举从中你可以得到一个数值,但它似乎到5月的唯一方式,发生的是通过一个副作用...我认为:)

Answer 1:

该角色Enumerator对象是饲料中的元素到iteratee按照特定的顺序,直到有没有更多的元素,或直至iteratee完成,然后返回iteratee。 该close()调用指示时,有没有更多的投入,使得iteratee结果可以返回。 如果没有调用close它可能仍然会有更多的推动。 所以,我没有试过,但我希望这将相当于你的例子:

val i = enumerateUsers |>> consumeOne
i.flatMap(_.run).onRedeem(println) // we will have a result we want to print
// now feed some data
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
// no more input, trigger promise computation
enumerateUsers.close() 

如果应用是更有意义enumerateUsers到iteratee,你不能提前告诉它有多少元素需要得到的结果(一般情况下)。



文章来源: Why does Play's PushEnumerator need to close() before the iterator will complete?