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

Как подождать, когда будет настроено готовое приложение WebSocket

Я пытаюсь реализовать WebSocket с возвратом к опросу. Если соединение WebSocket преуспевает, readyState становится 1, но если он терпит неудачу, readyState равно 3, и я должен начать опрос.

Я пробовал что-то вроде этого:

var socket = new WebSocket(url);
socket.onmessage = onmsg;
while (socket.readyState == 0)
{
}
if (socket.readyState != 1)
{
    // fall back to polling
    setInterval(poll, interval);
}

Я ожидал, что socket.readyState обновится асинхронно, и позвольте мне прочитать его немедленно. Однако, когда я запускаю это, мой браузер зависает (я оставил его открытым примерно на полминуты, прежде чем сдаваться).

Я подумал, что возможно событие onreadyStateChanged, но я не видел его в ссылке MDN.

Как мне это реализовать? По-видимому, пустой цикл не будет работать, и для этого события нет.

4b9b3361

Ответ 1

Это просто и работает отлично... вы можете добавить условие о максимальном времени или количестве попыток, чтобы сделать его более надежным...

function sendMessage(msg){
    // Wait until the state of the socket is not ready and send the message when it is...
    waitForSocketConnection(ws, function(){
        console.log("message sent!!!");
        ws.send(msg);
    });
}

// Make the function wait until the connection is made...
function waitForSocketConnection(socket, callback){
    setTimeout(
        function () {
            if (socket.readyState === 1) {
                console.log("Connection is made")
                if (callback != null){
                    callback();
                }
            } else {
                console.log("wait for connection...")
                waitForSocketConnection(socket, callback);
            }

        }, 5); // wait 5 milisecond for the connection...
}

Ответ 2

Вот более подробное объяснение. Прежде всего, проверьте конкретный API-интерфейс браузера, так как не все браузеры будут на последнем RFC. Вы можете обратиться к

Вы не хотите запускать цикл, чтобы постоянно проверять readistate, это дополнительные накладные расходы, которые вам не нужны. Лучший подход заключается в том, чтобы понять все события, имеющие отношение к изменению readistate, и затем подключить их соответствующим образом. Они выглядят следующим образом:

onclose Вызов вызывающего события, когда соединение ReadySate для подключения к WebSocket изменяется на CLOSED. Слушатель получает CloseEvent с именем "закрыть".

onerror При возникновении ошибки вызывается прослушиватель событий. Это простое событие с именем "ошибка".

onmessage Слушатель событий, вызываемый при получении сообщения от сервера. Слушатель получает MessageEvent с именем "сообщение".

onopen Вызов вызывающего события, когда соединение ReadySate для подключения к WebSocket изменяется на OPEN; это означает, что соединение готово для отправки и приема данных. Событие является простым с именем "open".

JS полностью управляется событиями, поэтому вам нужно просто подключить все эти события и проверить для readistate, таким образом вы можете переключиться с WS на опрос соответственно.

Я рекомендую вам взглянуть на ссылку Mozilla, ее легче читать, чем документ RFC, и это даст вам хороший обзор API и как он работает: см. https://developer.mozilla.org/en-US/docs/WebSockets/WebSockets_reference/WebSocket

Не забудьте сделать обратный вызов для повторной попытки, если у вас есть сбой и опрос, пока не будет вызван обратный вызов для успешного повторного подключения.

Ответ 3

Посмотрите на http://dev.w3.org/html5/websockets/

Найдите "Обработчик событий" и найдите таблицу.

onopen → открыть
onmessage → сообщение
ошибка → ошибка
закрыть → закрыть

function update(e){ /*Do Something*/};
var ws = new WebSocket("ws://localhost:9999/");

ws.onmessage = update;

Ответ 4

Я вообще не использую объединение. Вместо этого я использую очередь. Сначала я создаю новую функцию отправки и очередь:

var msgs = []
function send (msg) {
  if (ws.readyState !== 1) {
    msgs.push(msg)
  } else {
    ws.send(msg)
  }
}

Затем мне нужно прочитать и отправить, когда соединение установлено:

function my_element_click () {
  if (ws == null){
    ws = new WebSocket(websocket_url)
    ws.onopen = function () {
      while (msgs.length > 0) {
        ws.send(msgs.pop())
      }
    }
    ws.onerror = function(error) {
      // do sth on error
    }
  } 
  msg = {type: 'mymessage', data: my_element.value}
  send(JSON.stringify(msg))
}

Соединение WebSocket в этом примере создается только при первом щелчке. Обычно, по второму сообщению начинают посылаться напрямую.

Ответ 5

Ваш цикл while, вероятно, блокирует ваш поток. Попробуйте использовать:

setTimeout(function(){
    if(socket.readyState === 0) {
        //do nothing
    } else if (socket.readyState !=1) {
        //fallback
        setInterval(poll, interval);
    }
}, 50);

Ответ 6

В моем случае использования, я хотел показать ошибку на экране, если соединение терпит неудачу.

let $connectionError = document.getElementById("connection-error");

setTimeout( () => {
  if (ws.readyState !== 1) {
    $connectionError.classList.add( "show" );
  }
}, 100 );  // ms

Обратите внимание, что в Safari (9.1.2) событие error не запускается, иначе я бы поместил его в обработчик ошибок.

Ответ 7

Так же, как вы определили обработчик onmessage, вы также можете определить обработчик onerror. Этот вызов будет вызываться, когда соединение завершится с ошибкой.

var socket = new WebSocket(url);
socket.onmessage = onmsg;
socket.onerror = function(error) {
    // connection failed - try polling
}