2013年4月4日木曜日

WebSocket onopenのイベントハンドラは必ず呼び出されるのか

WebSocket を勉強しています。

WebSocket には onopen, onmessage, onclose というイベントが用意されています。
こんな感じで使います。
var wstest = function() {
  var ws = new WebSocket("ws://localhost:8000/");

  // 1秒待つ
  var d1 = new Date().getTime();
  var d2 = new Date().getTime();
  while (d2 < d1 + 1000) {
    d2 = new Date().getTime();
  }

  // イベントハンドラ登録
  ws.onopen = function() {
    console.log("websocket opened");
  };
  ws.onmessage = function(e) {
    console.log(e.data);
  };
  ws.onclose = function() {
    console.log("websocket closed");
  };
};

1秒待つ部分は、今回の疑問を実験するために挿入しています。
new WebSocket でソケットを生成してからイベントハンドラの登録までのタイムラグが、どのような影響を与えるかを調べたかったのです。

僕の予想では、 new WebSocket で生成された直後からサーバーへの接続処理が始まって、イベントハンドラの登録はすでにソケットが開かれた後に行われ、結果としてイベントハンドラが呼ばれないはずでした。
しかし、予想に反して、ソケットの接続処理は1秒後に行われ、 onopen イベントがきちんと発生し、イベントハンドラが呼び出されました。
サーバー側でも、1秒後に onopen イベントが呼び出されていました。

どうやら、 new WebSocket した関数(wstest)を抜け出してからサーバーへの接続処理が行われるのでは、と推測できます。
この動作が WebSocket の規格なのか、たまたま Google Chrome ではそのように動いたのかは定かではありません。しかし、僕が調べた限り WebSocket の使い方を解説しているサイトには、 new WebSocket した後で onopen イベントハンドラを登録するやり方しか載っていませんでしたので、きっとそれが正規の方法なのだと思うことにします。