在playframework中使用Streams,Enumerator和Websockets

时间:2013-11-14 17:53:39

标签: scala playframework websocket

我正在寻找在我的代码中使用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”可能是原因,但我错了,问题必须是服务器端,我没有线索..

1 个答案:

答案 0 :(得分:0)

来自Enumerator上的Enumerator ScalaDocs,描述了检索器功能:

  

输入功能。如果有要传递的输入,则返回最终使用Some值兑换的未来;如果已到达流的末尾,则返回最终使用None兑换的未来。

这意味着枚举器将从队列中拉出所有内容开始。当它为空时,回调将返回None。枚举器将此视为流的末尾,并且关闭会向下游发送完成状态。它不会再寻找任何数据

尝试将Enumerator / Iteratee范例推送到您的worker中,而不是使用可变队列进行消息传递。创建一个枚举器,输出您正在创建的实例,并让迭代器从中拉出。如果需要,你可以在中间添加一些枚举来进行一些变换。