Documentation

§Comet ソケット

§Comet ソケットを作成するためにチャンクレスポンスを利用する

チャンクレスポンス を応用すると、Comet ソケットを作成することができます。 Comet ソケットは、 <script> のみを含むチャンク分割された単なる text/html レスポンスです。それぞれのチャンクに、 web ブラウザによって実行される JavaScript を含んだ <script> タグを書き込みます。これを利用することで、サーバから web ブラウザへ、イベントをリアルタイムに送信することができます。 それぞれのメッセージ毎に、JavaScript のコールバック関数を呼び出す <script> タグでイベントをラップして、それをチャンクレスポンスに書き込みます。

それでは、これを確かめるデモを作成してみましょう。まず、ブラウザの console.log 関数を呼び出す <script> タグを生成するような Enumerator を作成します。

def comet = Action {
  val events = Enumerator(
    """<script>console.log('kiki')</script>""",
    """<script>console.log('foo')</script>""",
    """<script>console.log('bar')</script>"""
  )
  Ok.chunked(events).as(HTML)
}

このアクションを web ブラウザから実行すると、ブラウザのコンソールに3つのイベントログが出力されるでしょう。

Enumerator[A] を別の Enumerator[B] へ変換する play.api.libs.iteratee.Enumeratee を利用すると、この例はもっと簡単に書けます。試しに、標準的なメッセージを <script> タグでラップするのに使ってみましょう。

import play.twirl.api.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.chunked(events &> toCometMessage)
}

ヒント: events &> toCometMessageevents.through(toCometMessage) の別の書き方です

§play.api.libs.Comet ヘルパーを使う

チャンク分割された comet ストリームを扱うために、上で書いた内容とほぼ同じことを行う Comet ヘルパーを用意しています。

メモ: 実際のところ Comet ヘルパーは、ブラウザの互換性のため最初に空のバッファデータを送信したり、メッセージとして String と JSON の両方をサポートするなど、上で書いた内容以上のことを行います。さらに、特定の type class を定義することで、他の型のメッセージをサポートするように拡張することもできます。

これを使って前述の例を書き直してみましょう。

def comet = Action {
  val events = Enumerator("kiki", "foo", "bar")
  Ok.chunked(events &> Comet(callback = "console.log"))
}

§Forever iframe テクニック

Comet ソケットを書く標準的なテクニックとして、 iframe 内でチャンク分割された Comet レスポンスを無限にロードし、親フレームを呼び出すコールバック関数を特定するというものがあります。

def comet = Action {
  val events = Enumerator("kiki", "foo", "bar")
  Ok.chunked(events &> Comet(callback = "parent.cometMessage"))
}

これを、次のような HTML ページと共に使用します。

<script type="text/javascript">
  var cometMessage = function(event) {
    console.log('Received event: ' + event)
  }
</script>

<iframe src="/comet"></iframe>

Next: WebSocket


このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。