javascript websockets - контролировать начальное соединение / когда onOpen привязывается - PullRequest
27 голосов
/ 06 декабря 2011

Два связанных вопроса, которые могут быть более укоренены в моем незнании того, как / если браузеры предварительно разбирают javascript:

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

Кажется, что нет никакого способа напрямую контролировать инициализацию WebSocket, кроме оборачивания его в обратный вызов, поэтому я предполагаю, что соединение создается, как только код javascript загружается и попадает в конструктор?

Когда свойство onOpen присоединяется к ws? Есть ли возможность возникновения состояния гонки (если по какой-то причине у вас был какой-то код между определением сокета и определением onOpen?), Так что onOpen неразрывно связан до / после установления соединения (I знаю, что вы можете проверить ws.readyState). В дополнение к этому, блокируется ли рукопожатие WebSocket?

Я понимаю, что на данный момент все это черновик, возможно, зависит от реализации, и я, возможно, упустил что-то ослепительно очевидное, но я не увидел ничего особенного в моих поисках / просмотре в Интернете через черновую спецификацию w3c, поэтому любая помощь в мое понимание внутренней работы websockets / javascript очень ценится!

Ответы [ 4 ]

30 голосов
/ 06 декабря 2011

JavaScript является однопоточным, что означает, что сетевое соединение не может быть установлено до тех пор, пока текущая область выполнения не будет завершена и выполнение сети не получит шанс на выполнение. Область выполнения может быть текущей функцией (функция connect в примере ниже). Таким образом, вы можете пропустить событие onopen, если будете связываться с ним очень поздно при использовании setTimeout, например в этом примере вы можете пропустить событие:

Просмотр: 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 named' никогда не выводится. Это потому, что мы пропустили событие.

Однако, если вы сохраните new WebSocket(...) и привязку к событию onopen в одной и той же области выполнения, то у вас нет шансов пропустить событие.

Для получения дополнительной информации о scope of execution и о том, как они ставятся в очередь, планируются и обрабатываются, ознакомьтесь с постом Джона Ресига о Таймеры в JavaScript .

2 голосов
/ 07 мая 2015

Обратите внимание на тот факт, что ввод / вывод может происходить в пределах объема выполнения. Например, в следующем коде

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 голосов
/ 16 января 2013

@ 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 для браузера. Я предполагаю, что пользовательские агенты игнорируют его или неправильно его интерпретируют.

1 голос
/ 06 декабря 2011

Фактический ввод-вывод не произойдет до тех пор, пока не завершится выполнение сценария, поэтому не должно быть условия гонки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...