Подтвердить что ты не робот

Javascript websockets - контролировать начальное соединение/когда onOpen get bound

Два связанных вопроса, которые могут быть более укоренены в моей нехватке знаний о том, как/если браузеры предварительно анализируют 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 очень ценится!

4b9b3361

Ответ 1

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 called" log никогда не выводится. Это потому, что мы пропустили это событие.

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

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

Ответ 2

@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 и продолжите эти шаги в фоновом режиме (без блокировки скриптов).

Это меня сбивало с толку, когда я изучал браузер для него. Я предполагаю, что пользовательские агенты игнорируют это, или я неправильно интерпретирую его.

Ответ 3

Обратите внимание на то, что операции ввода-вывода могут выполняться в рамках исполнения. Например, в следующем коде

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"

Ответ 4

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