如何在Play2中从ReactiveMongo返回JSON的枚举器
-
21-12-2019 - |
题
在我们的项目中,我们正在使用 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)
)
这有效,但感觉就像发明轮子。
对于这个常见问题,有更好的解决方案吗?
解决方案
如果您使用comet或EventSource,则不必手工制作一种生成输出的方法,并且您实际上还能够解析客户端中item的响应项。使用数组进行响应将迫使您编写自己的解析代码,或者等到所有内容都到达客户端,然后才能在JavaScript中使用build int JSON解析器。
使用EventSource协议进行流式传输非常容易,您应该能够执行以下操作:
implicit val cometEncoder = new Comet.CometMessage[JsValue](_.toString)
Ok.chunked(yourEnumerator &> EventSource()).as(EVENT_STREAM)
然后在客户端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>
在play示例项目中也有一个这样的例子,你可能也想看看 $YOUR_PLAY_DIR/samples/scala/eventsource-clock/
不隶属于 StackOverflow