我有一个页面由我使用不同的远程服务器调用获得的数据填充。有些请求比其他请求花费的时间更长,我现在做事的方式是我立即执行所有调用并将整个事件包装在Future
中,然后将整个事件放在Action.async
中用于播放处理。
理论上,这可以完成这项工作,但我不希望我的用户等待很长时间,而是开始逐个加载页面。这意味着只要数据可用于远程服务器的给定请求,就应该将其作为Json或其他任何内容发送给客户端。
我可以使用EventSource部分实现这一点,方法是通过这样的方式修改Play的事件源示例:
Ok.chunked((enumerator1 &> EventSource()) >- (enumerator2 &> EventSource())).as("text/event-stream")
和枚举者如下:
val enumerator1: Enumerator[String] = Enumerator.generateM{
Future[Option[String]]{Thread.sleep(1500); Some("Hello")}
}
val enumerator2: Enumerator[String] = Enumerator.generateM{
Future[Option[String]]{Thread.sleep(2000); Some("World!")}
}
正如你可能已经猜到的那样,我期待着"你好" 1.5秒后然后"世界!" 0.5秒后发送给客户,但我最终收到了#34; Hello"每1.5秒和#34;世界!"每2秒。
我的问题是:
使用上述方法将信息正确传送到客户后,是否有办法停止发送信息?
有没有更好的方法来实现我的目标?
答案 0 :(得分:0)
您不希望generateM
,它可以构建可以返回多个值的枚举器。 generateM
使用一个函数返回Some
,生成Enumerator
或None
的下一个值,以表示Enumerator
已完成。因为您的函数始终返回Some
,所以您创建了长度无限的Enumerator
。
您只想将Future
转换为Enumerator
,以使用单个元素创建Enumerator
:
Enumerator.flatten(future.map(Enumerator(_)))
此外,您可以交错您的枚举器,然后将结果提供给EventSource()
。括号也是不必要的(以>
开头的方法优先于&
的方法。
enumerator1 >- enumerator2 &> EventSource()