web-dev-qa-db-ja.com

javascript websockets-初期接続を制御する/ onOpenがバインドされるタイミング

2つの関連する質問は、ブラウザがJavaScriptを事前に解析する方法/場合に関する私の知識の欠如に根ざしている可能性があります。

var ws = new WebSocket("ws://ws.my.url.com");
ws.onOpen = function() { ... };

WebSocketの初期化を直接制御する方法はないようです。コールバックでラップする以外に、JavaScriptコードが読み込まれてコンストラクターに到達するとすぐに接続が作成されると思いますか?

onOpenプロパティはいつwsにアタッチされますか?競合状態が発生する可能性はありますか(何らかの理由でソケットの定義とonOpenの定義の間にコードがあった場合)、onOpenが予測不能に前/後にバインドされます。接続が確立されました(オプションでws.readyState)。これを補足すると、WebSocketハンドシェイクはブロックされますか?

現時点ではドラフトであり、実装に依存している可能性があり、目立たないように見逃している可能性がありますが、w3c仕様のドラフトでインターネット検索/スキムに特に関連するものは見当たらないので、私の理解に役立つwebsockets/javascriptの内部の仕組みは非常に高く評価されています!

28
dbeacham

JavaScriptはシングルスレッドです。つまり、現在の実行スコープが完了し、ネットワークの実行が実行されるまで、ネットワーク接続を確立できません。実行範囲は、現在の関数(以下の例ではconnect関数)にすることができます。したがって、setTimeoutを使用して非常に遅くにバインドすると、onopenイベントを見逃す可能性があります。この例では、イベントを見逃す可能性があります。

表示: http://jsbin.com/ulihup/edit#javascript,html,live

コード:

_var ws = null;

function connect() {
  ws = new WebSocket('ws://ws.pusherapp.com:80/app/a42751cdeb5eb77a6889?client=js&version=1.10');
  setTimeout(bindEvents, 1000);
  setReadyState();
}

function bindEvents() {
  ws.onopen = function() {
    log('onopen called');
    setReadyState();
  };
}

function setReadyState() {
  log('ws.readyState: ' + ws.readyState);
}

function log(msg) {
  if(document.body) {
    var text = document.createTextNode(msg);
    document.body.appendChild(text);
  }
}

connect();
_

この例を実行すると、「onopen called」ログ行が出力されないことがよくわかります。これは、イベントに参加できなかったためです。

ただし、new WebSocket(...)onopenイベントへのバインディングを同じ実行範囲に維持すると、イベントを見逃すことはありません。

_scope of execution_の詳細と、これらがどのようにキューに入れられ、スケジュールされ、処理されるかについては、John Resigの JavaScriptのタイマー に関する投稿をご覧ください。

30
leggetter

実行範囲内でI/Oが発生する可能性があることに注意してください。たとえば、次のコードでは

var ws = new WebSocket("ws://localhost:8080/WebSockets/example");
alert("Hi");
ws.onopen = function(){
    writeToScreen("Web Socket is connected!!" + "<br>");
};
function writeToScreen(message) {
    var div = document.getElementById('test');
    div.insertAdjacentHTML( 'beforeend', message );
}

、 メッセージ "Web Socket is connected"は、閉じるのにかかった時間に応じて、表示されるかどうかにかかわらず"Hi"アラート

2
Alon Halimi

@ leggetter が正しい、次のコードは順次実行されました:

(function(){
    ws = new WebSocket("ws://echo.websocket.org");
    ws.addEventListener('open', function(e){
        console.log('open', e);
        ws.send('test');
    });
    ws.addEventListener('message', function(e){console.log('msg', e)});

})();

しかし、 W3C spec には奇妙な行があります:

新しいWebSocketオブジェクトを返し、これらの手順を(スクリプトをブロックせずに)バックグラウンドで続行します。

私がブラウザAPIを学んでいたとき、それは私を混乱させました。私はユーザーエージェントがそれを無視していると思います、または私はそれを誤って解釈しています。

2
senz

スクリプトの実行が完了するまで実際のI/Oは発生しないため、競合状態は発生しません。

1
Jacob