Часть 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. Однако, если вы внимательно посмотрите или попробуете сами, вы увидите, что событие закрытия регистрируется непосредственно перед обновлением страницы.