我正在寻找在我的代码中使用play的枚举器(play.api.libs.iteratee.Enumerator [A])的正确方法,我有一个“InfoBlock”类型的对象流,我想重定向它到websocket。我实际做的是:
持有块的数据结构
private lazy val buf:mutable.Queue [InfoBlock] = new mutable.SynchronizedQueue [InfoBlock]
要在Enumerator中使用的回调
def getCallback: Future[Option[InfoBlock]] = Future{
if (!buf.isEmpty)
Some(buf.dequeue)
else
None}
Block由另一个线程生成,并使用以下命令添加到队列中:
buf += new InfoBlock(...)
然后在控制器中我想设置一个websocket来传输这些数据,执行:
def stream = WebSocket.using[String]{ request =>
val in = Iteratee.consume[String]()
val enu:Enumerator[InfoBlock] = Enumerator.fromCallback1(
isFirst => extractor.getCallback
)
val out:Enumerator[String] = enu &> Enumeratee.map(blk => blk.author+" -> "+blk.msg)
(in,out)}
它有效,但有一个大问题,当一个连接打开它发送一堆块(= ~50)并停止,如果我打开一个新的websocket然后我得到另一堆块但没有更多。我试图设置一些属性到js对象WebSocket,特别是我尝试设置
websocket.binaryType = "arraybuffer"
因为我认为使用“blob”可能是原因,但我错了,问题必须是服务器端,我没有线索..
答案 0 :(得分:0)
来自Enumerator上的Enumerator ScalaDocs,描述了检索器功能:
输入功能。如果有要传递的输入,则返回最终使用Some值兑换的未来;如果已到达流的末尾,则返回最终使用None兑换的未来。
这意味着枚举器将从队列中拉出所有内容开始。当它为空时,回调将返回None。枚举器将此视为流的末尾,并且关闭会向下游发送完成状态。它不会再寻找任何数据
尝试将Enumerator / Iteratee范例推送到您的worker中,而不是使用可变队列进行消息传递。创建一个枚举器,输出您正在创建的实例,并让迭代器从中拉出。如果需要,你可以在中间添加一些枚举来进行一些变换。