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

Как поддерживать соединение WebSockets между страницами?

В одном из моих сценариев у меня есть этот код:

var webSocket = window.WebSocket || window.MozWebSocket;
window.ws = new webSocket('ws://64.121.210.140:2585/consoleappsample', 'my-protocol');

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

Я попытался поместить window.ws в глобальную область видимости, но, похоже, это не устранило проблему. Есть ли способ, по которому соединение WebSockets сохраняется между страницами, чтобы соединение не нуждалось в постоянном восстановлении?

4b9b3361

Ответ 1

Глобальная область, о которой вы говорили, всегда связана с контекстом JavaScript, и для каждого окна создается Контекст (и уничтожается, когда документ выгружается из памяти). Поэтому ваши усилия бесполезны: вы не можете сохранить соединение открытым, если пользователь меняет страницу. Конечно, вы можете использовать ваш webapp как приложение "одна страница", где все данные загружаются с использованием XMLHttpRequest/ajax/WebSocket. Таким образом, оставляя страницу, означает выключение/выключение приложения и имеет смысл закрыть сокет.

Еще один старый подход может быть помещен вашими страницами в фрейм, где пользователь перемещается только в фрейме (даже если он принимает весь размер окна). Таким образом, вы можете создать свой WebSocket в самом верхнем окне, которое никогда не будет изменено (это также означает, что URL-адрес, отображаемый на панели местоположений, будет всегда одинаковым).

Сказал, что я согласился с @dystroy: ваше приложение всегда должно справляться с этим сценарием - у пользователя может быть какая-то проблема с сетью и на какое-то время потеряло соединение, даже если оно не покидает страницу.

Ответ 2

Вы можете попробовать создать соединение с WebSocket в Shared WebWorker, который позволяет нескольким страницам из одного домена совместно использовать контекст выполнения. Тем не менее, неясно, сохраняются ли общие рабочие на перезагрузке страницы или заменяются: Предоставляют ли общие веб-работники перезагрузку одной страницы, ссылку на ссылку.

Кроме того, Shared WebWorkers теперь ограниченная поддержка браузера (webkit и Opera).

Обновление

Поскольку один общий веб-рабочий может обслуживать несколько страниц, реализация немного сложнее, чем обычные рабочие сети.

Вот пример совместного веб-работника, который использует WebSockets и может делиться между

Сначала HTML:

<!DOCTYPE html>
<html>
<body>
<script>
    var worker = new SharedWorker("shared.js");
    worker.port.addEventListener("message", function(e) {
        console.log("Got message: " + e.data);
    }, false);
    worker.port.start();
    worker.port.postMessage("start");
</script>
</body>
</html>

Javascript, который реализует общий рабочий в shared.js:

var ws = null
var url = "ws://" + location.hostname + ":6080"
self.addEventListener("connect", function(e) {
    var port = e.ports[0]
    port.addEventListener("message", function(e) {
        if (e.data === "start") {
            if (ws === null) {
                ws = new WebSocket(url);
                port.postMessage("started connection to " + url);
            } else {
                port.postMessage("reusing connection to " + url);
            }
        }
    }, false);
    port.start();
}, false);

Я проверил, что это работает в Chrome 52.

Ответ 3

К сожалению, самое чистое решение без изменения вашего сайта в SPA-приложении получается с использованием только одного ServiceWorker, потому что он выполняет задание в фоновом режиме (также с закрытой вкладкой) и решает также проблемы с несколькими вкладками. Я сказал "к несчастью", потому что они все еще не совместимы с большинством браузеров. Единственное решение, которое я нашел сам, состоит из группировки сокетных каналов на стороне сервера и создания очереди для удержания сообщений, потерянных при смене страницы. В этом случае у вас есть виртуальные каналы.