在Play框架中将WebSockets从2.4版转换为2.6
问题描述:
我试图将这个代码转换为使用Play版本2.4到当前版本(2.6),并且我遇到了一些问题,因为我仍然是一个noob斯卡拉。在Play框架中将WebSockets从2.4版转换为2.6
def wsWeatherIntervals = WebSocket.using[String] {
request =>
val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
val outEnumerator = Enumerator.repeatM[String]({
Thread.sleep(3000)
ws.url(url).get().map(r => s"${new java.util.Date()}\n ${r.body}")
})
(Iteratee.ignore[String], outEnumerator)
}
我跟着this guide,但现在我卡上,我应该对方法返回的东西。 这是我尝试使用2.6版本来运行代码:
import play.api.mvc._
import scala.concurrent.Future
import akka.stream.scaladsl._
def wsWeatherIntervals = WebSocket.accept[String, Future[String]] { res =>
val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
val source = Source.repeat({
Thread.sleep(3000)
ws.url(url).get().map(r => s"${new java.util.Date()}\n ${r.body}")
})
Flow.fromSinkAndSource(Sink.ignore, source)
}
但运行的服务器,指向方法的第一线时,我得到这个错误:
could not find implicit value for parameter transformer: play.api.mvc.WebSocket.MessageFlowTransformer[String,scala.concurrent.Future[String]]
注意:我也尝试致电WebSocket.apply
而不是WebSocket.accept
,我做了一些关于两者之间的差异的搜索,但没有发现任何有用的东西。有人可以解释两者之间的区别吗?谢谢。
答
表面上的错误是,Play不知道如何将Future[String]
变成Websocket消息,为此你通常使用隐式转换器。然而,在这种情况下,你不想返回Future[String]
反正只是它可以自动编组(使用提供stringMessageFlowTransformer
,因为它发生。)一个普通字符串这里的东西应该工作:
def wsWeatherIntervals = WebSocket.accept[String, String] { res =>
val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
def f = ws.url(url).get().map(r => s"${new java.util.Date()}\n ${r.body}")
val source = Source.unfoldAsync(f)(last => {
Thread.sleep(3000)
f.map(next => Some((last, next)))
})
Flow.fromSinkAndSource(Sink.ignore, source)
}
的unfoldAsync
源让我们重复运行一个函数,返回流中下一个元素的未来。 (因为我们想让流永远继续下去,我们返回包装成Some
值)。
的Websocket.apply
方法基本上是accept
更复杂的版本,它允许您通过返回的响应,拒绝某种原因WebSocket连接,但是如果你需要这样做,最好使用acceptOrResult
,它可以处理任何流向websocket消息发送的变换。