Должен ли WebSocket.onclose запускаться пользователем или обновляться?

Часть 1: Ожидаемое поведение?

Я вижу противоречивое поведение браузера между Firefox и Chrome по отношению к onclose вызывается обработчик.

Похоже, что Chrome не вызывает onclose если это было вызвано навигацией / обновлением страницы пользователя. Тем не менее, Firefox действительно вызывает onclose,

Мне кажется, что Firefox может вести себя правильно здесь:

Когда соединение WebSocket закрыто, возможно, чисто, пользовательский агент должен создать событие, которое использует интерфейс CloseEvent, с именем события close, которое не всплывает, не может быть отменено, не имеет действия по умолчанию, для атрибута wasClean которого установлено значение true если соединение закрыто чисто и ложно, в противном случае, чей атрибут кода установлен как код закрытия соединения WebSocket, а атрибут причины установлен как причина закрытия соединения WebSocket; и поставьте в очередь задачу, чтобы сначала изменить значение атрибута readyState на CLOSED (3), а затем отправить событие в объект WebSocket.

Источник: http://www.w3.org/TR/2011/WD-websockets-20110419/

Хотя это может привести к некоторому подлому коду / неожиданному поведению.

Кто-нибудь может подтвердить ожидаемое поведение?

Часть 2: Как реализовать автоматическое переподключение?

Если у вас есть библиотека, которая автоматически переподключается для пользователя, как узнать, стоит ли пытаться переподключиться? Вы проверяете CloseEvent.wasClean имущество? Я должен предположить, что "чистый" означает, что закрытие должно было произойти через вызов API WebSocket.close() или сервер отправляет закрытый кадр? Если ошибка сети вызывает закрытие, я думаю, wasClean было бы false?

В библиотеке JavaScript Pusher мы предполагали (onclose -> wait -> connection), что закрытие должно инициировать повторное соединение, если только мы не находимся в закрытом состоянии - разработчик решил закрыть соединение. Казалось бы, клиентская библиотека socket.io делает то же самое.

Исходя из этого, событие onflose Firefox, вызванное пользовательской навигацией / обновлением, вызывает нежелательное переподключение, поскольку ни одна из библиотек не проверяет CloseEvent.wasClean имущество.

Пример и видео

Вот пример, который вы можете использовать для демонстрации несоответствия: http://jsbin.com/awonod/7

Вот мое видео, демонстрирующее проблему: http://www.screenr.com/vHn8 (уже поздно, не обращайте внимания на пару промахов:))

Следует отметить, что мое нажатие клавиши Escape также может привести к закрытию соединения WebSocket. Однако, если вы внимательно посмотрите или попробуете сами, вы увидите событие закрытия, регистрируемое непосредственно перед обновлением страницы.

3 ответа

Неожиданное поведение связано с тем, как Firefox и Chrome обрабатывают закрытие веб-сокета. Когда страница обновляется, оба браузера закрывают соединение, однако Firefox выполнит ваш код onclose, в то время как Chrome закрывает соединение и сразу же перезагружает новую страницу. Так что да, я подтверждаю это странное поведение.
Еще более странным является тот факт, что, по моим наблюдениям, вызов websocket.close() в chrome немедленно закроет соединение и вызовет функцию onclose, в то время как Firefox ожидает закрытия сообщения с сервера.

Свойство wasClean будет иметь значение true, если с сервера было получено сообщение о закрытии

Если ваша библиотека автоматически переподключается без проверки свойства wasClean, это может вызвать проблему, поскольку она пытается восстановить соединение при обновлении страницы. Вам следует подумать о том, чтобы не использовать библиотеку для этого и делать это вручную, это не должно быть очень сложным, просто вызовите connect в функции onclose с помощью оператора if, чтобы убедиться, что свойство onclean имеет значение true. Или, чтобы быть более безопасным, установите переменную в onbeforeunload, которая предотвращает любое новое соединение.

надеюсь это поможет!

Удивительно, но это все еще актуально в 2022 году. Вы можете тривиально продемонстрировать это, добавив журнал консоли в обработчик onclose для веб-сокета и щелкнув ссылку в Firefox или в Chrome во время просмотра консоли (обеспечив сохранение консоли между веб-страницами) :

      ws.onclose = function(e) {
  printMsg('CLOSE')
  // ... my other code ...
}

Firefox покажет вам «ЗАКРЫТЬ», а Chrome — нет.

У меня есть несколько слов, чтобы добавить,

Когда вы обновляете страницу, вызывается событие "onclose", и большинство браузеров работают синхронно, если браузер работает асинхронно, то только он не будет закрыт.

Здесь синхронные средства подключаются при необходимости (обновление / навигация).

Асинхронные средства связаны всегда. так придется с webSocket. открыт всегда

https://developer.mozilla.org/@api/deki/files/6227/=AsyncUnload.jpg

Ссылка на закрытое мероприятие Mozilla Network

Веб-сокет

Здесь вы также найдете ответ на "wasClean", то есть полностью закрытый.

Я надеюсь, что это сложится..

Другие вопросы по тегам