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

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

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

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

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

Когда соединение WebSocket закрыто, возможно, чисто, пользовательский агент должен создать событие, которое использует интерфейс CloseEvent, с именем события close, которое не всплывает, не может быть отменено, не имеет действия по умолчанию, чей атрибут wasClean имеет значение true если соединение закрыто правильно и false в противном случае, чей атрибут code установлен на код закрытия соединения WebSocket, а чей атрибут Reason установлен на причину закрытия соединения 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 -> ожидание -> подключение), что закрытие должно вызывать повторное подключение, если только мы не находимся в состоянии закрытия — разработчик решил закрыть соединение. Похоже, что клиентская библиотека socket.io делает то же предположение.

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

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

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

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

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


person leggetter    schedule 10.06.2012    source источник
comment
Ссылка на Pusher такая же, как ссылка на socket.io. Также строка # больше не применима. Должен ссылаться на конкретную фиксацию, например github.com/ socketio/socket.io-client/blob/   -  person bennlich    schedule 20.01.2017


Ответы (1)


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

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

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

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

person Optox    schedule 18.06.2013