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

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

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

Кажется, что Chrome не запускает onclose, если он был вызван навигацией/обновлением пользовательской страницы. Однако Firefox запускает onclose.

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

Ссылка закрытого события Сеть Mozilla

Web Socket

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

Надеюсь, это скомпрометирует.