mav*_*azy 5 scala enumerator iterate playframework-2.0 reactivemongo
在我们的项目中,我们使用的是ReactiveMongo用Play 2.2.1.
问题是,Enumerator[A]返回的形式的数据流ReactiveMongo实际上是一个值对象流,它们没有逗号分隔,并且没有流开始和结束注释,可以视为数组打开和关闭声明.
这会给JSON消费者带来问题JS client,因为预期的格式是
[A1,A2, ...]
所以我们跳入了箍,并通过检查将我们Enumeratee[A]改为Enumerator[String],如果它是第一个元素,或者不是:
var first:Boolean = true
val aToStrs = (as.map(a => {
if(first) {
first = false;
Json.stringify(Json.toJson(a))
} else {
"," + Json.stringify(Json.toJson(a))
}
}))
Ok.chunked(
Enumerator.enumInput(Input.El("[")) andThen
aToStrs andThen
Enumerator.enumInput(Input.El("]")) andThen
Enumerator.enumInput(Input.EOF)
)
Run Code Online (Sandbox Code Playgroud)
这有效,但感觉就像发明轮子一样.
对于这个常见问题,有没有更好的解决方案?
如果您使用 comet 或 EventSource,您将不必手工制作一种生成输出的方法,并且您实际上还能够在客户端中解析项目的响应项目。使用数组进行响应将迫使您要么编写自己的解析代码,要么等到所有内容都到达客户端后才能在 JavaScript 中使用 build int JSON 解析器。
使用 EventSource 协议进行流式传输非常容易,您应该能够执行以下操作:
implicit val cometEncoder = new Comet.CometMessage[JsValue](_.toString)
Ok.chunked(yourEnumerator &> EventSource()).as(EVENT_STREAM)
Run Code Online (Sandbox Code Playgroud)
然后在客户端html中:
<script type="text/javascript">
var es = new EventSource(jsRouter.controllers.Application.streamIt().url)
es.addEventListener("message", function (event) {
var item = JSON.parse(event.data)
// ... do something with the json value ...
})
</script>
Run Code Online (Sandbox Code Playgroud)
您可能还想查看播放示例项目中的一个示例$YOUR_PLAY_DIR/samples/scala/eventsource-clock/