2012-05-17 53 views
3

下面的例子,改編自遊戲框架的文檔:爲什麼Play的PushEnumerator需要在迭代器完成之前關閉()?

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的答案是正確的,因爲他有點回答了這個問題,但我一直在尋找具體的答案非常簡單。 Play實現使用副作用來驅動套接字,這並非不合理 - 這不是我所假設的(假設會殺死所有的東西:D)。在play.core.server.netty.Helpers裏面有一個叫socketOut[A](...)的函數。 socketOut[A](...)具有稱爲step的函數,該函數返回一個Iteratee。當輸入案例匹配El(e)時,此迭代器將e寫入輸出通道。我的假設是,迭代器可以部分使用可以從中獲得價值的統計員,但似乎唯一可能發生的方式是通過副作用...我認爲:)

回答

2

Enumerator對象是以特定順序將元素提供給迭代器,直到沒有更多元素或迭代器完成並返回該迭代器爲止。調用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,你不能提前告訴它有多少元素需要獲得它更有意義結果(一般情況)。

+0

我將不得不嘗試挖掘Play源代碼,因爲我不清楚這是如何與WebSocket一起工作的。據我記得(我不是在正確的終端ATM),我保持'推'到WebSocket的出站枚舉。我不需要「關閉」它來讓它在線上產生東西,但每個「推」似乎都產生了。如果是這樣的話,那麼我就錯過了一些機制。 –

+0

@DerekWyatt,從技術上講,只要元素被推送,WebSocket可能不必提取迭代器的結果。所以可能這就是爲什麼沒有必要。 – huynhjl

+0

在我的問題結尾添加了我的發現。 –

相關問題