爲了建立Promise[Result],咱們首先須要另外一個promise:該promise將爲咱們計算實際的結果值。javascript
val promiseOfPIValue: Promise[Double] = computePIAsynchronously() val promiseOfResult: Promise[Result] = promiseOfPIValue.map { pi => Ok("PI value computed: " + pi) }
全部的 Play 2.0 的異步調用API會返回 Promise。無論你是使用 play.api.libs.WS API調用外部web服務,仍是藉助Akka分配異步任務,亦或使用 play.api.libs.Akka 在actors間通訊。
val promiseOfInt: Promise[Int] = Akka.future { intensiveComputation() }
def index = Action { val promiseOfInt = Akka.future { intensiveComputation() } Async { promiseOfInt.map(i => Ok("Got result: " + i)) } }
注意:Async { ... }是一個助手方法,用於從Promise[Result]中構建AsyncResult。
def index = Action { val promiseOfInt = Akka.future { intensiveComputation() } Async { promiseOfInt.orTimeout("Oops", 1000).map { eitherIntorTimeout => eitherIorTimeout.fold( timeout => InternalServerError(timeout), i => Ok("Got result: " + i) ) } } }
def index = Action { Ok("Hello World") }
然而,由於該內容是已知的,Play可以自行計算該長度併產生適當的響應頭信息。
def index = Action { SimpleResult( header = ResponseHeader(200), body = Enumerator("Hello World") ) }
val file = new java.io.File("/tmp/fileToServe.pdf") val fileContent: Enumerator[Array[Byte]] = Enumerator.fromFile(file)
它看起來正確嗎?咱們僅使用enumerator指定 response body:
def index = Action { val file = new java.io.File("/tmp/fileToServe.pdf") val fileContent: Enumerator[Array[Byte]] = Enumerator.fromFile(file) SimpleResult( header = ResponseHeader(200), body = fileContent ) }
def index = Action { val file = new java.io.File("/tmp/fileToServe.pdf") val fileContent: Enumerator[Array[Byte]] = Enumerator.fromFile(file) SimpleResult( header = ResponseHeader(200, Map(CONTENT_LENGTH -> file.length.toString)), body = fileContent ) }
def index = Action { Ok.sendFile(new java.io.File("/tmp/fileToServe.pdf")) }
def index = Action { Ok.sendFile( content = new java.io.File("/tmp/fileToServe.pdf"), fileName = _ => "termsOfService.pdf" ) }
val data = getDataStream val dataContent: Enumerator[Array[Byte]] = Enumerator.fromStream(data)
咱們如今能夠經過ChunkedResult處理這些數據:
def index = Action { val data = getDataStream val dataContent: Enumerator[Array[Byte]] = Enumerator.fromStream(data) ChunkedResult( header = ResponseHeader(200), chunks = dataContent ) }
一如既往,咱們提供了便利方法完成一樣工做:
def index = Action { val data = getDataStream val dataContent: Enumerator[Array[Byte]] = Enumerator.fromStream(data) Ok.stream(dataContent) }
固然咱們也能夠用任何的Enumerator指定塊數據:
def index = Action { Ok.stream( Enumerator("kiki", "foo", "bar").andThen(Enumerator.eof) ) }
Tip:Enumerator.callbackEnumerator and Enumerator.pushEnumerator convenient ways to create reactive non-blocking enumerators in an imperative style.
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Transfer-Encoding: chunked 4 kiki 3 foo 3 bar 0
咱們接收到了三塊數據,最後在接到到空塊後關閉該響應。
def comet = Action { val events = Enumerator( """<script>console.log('kiki')</script>""", """<script>console.log('foo')</script>""", """<script>console.log('bar')</script>""" ) Ok.stream(events >>> Enumerator.eof).as(HTML) }
若是你從瀏覽器中訪問該action,你將會在瀏覽器控制檯中看到三個日誌記錄。
import play.api.templates.Html // Transform a String message into an Html script tag val toCometMessage = Enumeratee.map[String] { data => Html("""<script>console.log('""" + data + """')</script>""") } def comet = Action { val events = Enumerator("kiki", "foo", "bar") Ok.stream(events >>> Enumerator.eof &> toCometMessage) }
提示:編寫 events >>> Enumerator.eof &> toCometMessage 只是 events.andThen(Enumerator.eof).through(toCometMessage) 的另外一種形式。
def comet = Action { val events = Enumerator("kiki", "foo", "bar") Ok.stream(events &> Comet(callback = "console.log")) }
def comet = Action { val events = Enumerator("kiki", "foo", "bar") Ok.stream(events &> Comet(callback = "parent.cometMessage")) }
<script type="text/javascript"> var cometMessage = function(event) { console.log('Received event: ' + event) } </script> <iframe src="/comet"></iframe>
def index = WebSocket.using[String] { request => // Log events to the console val in = Iteratee.foreach[String](println).mapDone { _ => println("Disconnected") } // Send a single 'Hello!' message val out = Enumerator("Hello!") (in, out) }
WebSocket具有檢索請求頭(從HTTP請求頭啓動一個WebSocket鏈接)能力,容許你取回標準頭消息和session數據。然而它不具有訪問 request body 和HTTP response body 的能力。
def index = WebSocket.using[String] { request => // Just consume and ignore the input val in = Iteratee.consume[String]() // Send a single 'Hello!' message and close val out = Enumerator("Hello!") >>> Enumerator.eof (in, out) }