2

我試圖將這個代碼轉換爲使用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,我做了一些關於兩者之間的差異的搜索,但沒有發現任何有用的東西。有人可以解釋兩者之間的區別嗎?謝謝。

回答

2

表面上的錯誤是,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消息發送的變換。

相關問題