Cometメッセージハンドラのクライアントチュートリアル

comet.html

CometBroker を使うクライアントとして、mpchat_webclient/comet.html が提供されている。 これは ajax.html の送受信を分けて行うようにしたものである。

ライブラリのロード

HTML は最初に js ファイルをいくつかロードしている:
  <head>
    <script type='text/javascript' src='../mpchat_message/nmljs/json2.js'></script>
    <script type='text/javascript' src='../mpchat_message/nmljs/libnine.js'></script>
    <script type='text/javascript' src='../mpchat_message/nmljs/message.js'></script>

json2.js は http://www.json.org/json2.jsで配布されているもので、JavaScript 用の JSON ライブラリである。これはまた nineml にも同梱されている。

libnine.js は nineml から生成した JavaScript コードを使う際に必要とされるライブラリである。 nine/tool/nineml に同梱されている。

message.js は、mpchat_message/message.xml から生成された JavaScpirt コードである。

メッセージの送信

メッセージ送信は sendRequest(channel, qs) 関数に一元化されている。

function sendRequest(channel, qs) {
  var host = document.getElementById('input_host').value;
  var port = document.getElementById('input_port').value;

  var url = 'http://' + host + ':' + port + '/comet/' + channel + '?uniq=' + _uniq;
  url += '&' + qs;
  ++_uniq;

  var script     = document.createElement( 'script' );
  script.type    = 'text/javascript';
  script.charset = 'utf-8';
  script.src     = url;
  document.getElementsByTagName("head")[0].appendChild(script)
}

引数の channel, qs は、リクエストパスの構成に使われる。 特に、channel には "u" か "d" の文字列を与えることで、接続がダウンロードかアップロードかを決めることになる。

最初の接続

HTTPセッションの識別子は、最初の接続の応答で指定される。

セッションが未定のまま Comet の二本の接続をしてしまうと、二本別々のセッションが割り当てられてしまうことになる。

これを避けるため、クライアントの初期化の一環としてダミーの要求を送るようにしている。

function doConnect() {
  sendRequest('u', 'jsonp=onHandshake');
}
function onHandshake() {
  cometDown();
}
function cometDown() {
  sendRequest('d', 'jsonp=onMessage');
}

doConnect() は、GUI から Comet への接続が要求された時に呼ばれる。

doConnect() では sendRequest() でアップロード用チャネル接続を開始する。クエリ文字列には "jsonp=onHandshake" を指定している。 CometMessageHandler の仕様では、アップロードチャネルの応答は常に空の配列が返るようになっている。JSONP の指定は有効なので、onHandshake() 関数がコールバックされることになる。

doConnect で送ったリクエストの応答には、Comet のセッションIDが cookie で指定されている。 よって、onHandshake() 以降の sendRequest() 呼び出しは正しく Comet セッションが指定されるようになる。

onHandshake() は cometDown() 関数を呼ぶ。 cometDown() は sendRequest() に 'd' を渡すことで、ダウンロード用の接続を張る関数である。 同時に jsonp に onMessage を指定し、ダウンロードチャネルから応答が来ると onMessage() 関数を呼びだすようにしている。

発言の送信

発言が GUI から指定されると、doSay() が呼ばれる:
function doSay(say) {
  var msg = new ChatRequest();
  msg.chat.name = name;
  msg.chat.chat = say;
  msg.from = _lastIndex;

  var qs = nine.marshal_querystring(msg);
  sendRequest('u', 'jsonp=onUp&' + qs);
}
function onUp(dummy) {
}
ChatRequest オブジェクトを生成し、プロパティをセットアップして sendRequest() へ送っている。

sendRequest ではアップロードチャネルを指定し、コールバック関数は onUp である。

アップロードチャネルの応答はメッセージは含まれないので、onUp で何かのデータ操作を行う必要はない。

メッセージの受信

cometDown() で作られたダウンロードチャネルでは、コールバックに onMessage 関数を指定している。 よって、サーバーからのメッセージは全て onMessage で捉えることができる。

function onMessage(ary) {
  var msg;
  for (var i=0; i<ary.length; ++i) {
    msg = nine.unmarshal_json_object(ary[i]);
    if (msg.messageId == LogNotify.MESSAGE_ID) {
      addLog(msg);
    }
  }
  cometDown();
}

前半の for ループでは、ajax.html と同様に配列要素のオブジェクトを nine メッセージへ変換して、チャットログへ追記している。

最後に cometDown() を呼び、新たなダウンロードチャネルの構築を行う。