在Play框架中将WebSockets从2.4版转换为2.6

在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消息发送的变换。