Кроссбраузерная оконная коммуникация, 7 способов, сколько вы знаете?

внешний интерфейс JavaScript
Кроссбраузерная оконная коммуникация, 7 способов, сколько вы знаете?

Это 30-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления.

предисловие

Почему эта тема поднята?y.qq.com/QQ музыка,

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

Здесь я снова думаю о сцене с тележкой для покупок в торговом центре, и впечатление действительно улучшилось.
В начале я подозревал, что Web Socket — демон, но проанализировав сетевой запрос и посмотрев исходный код, не понял. Наконец-то обнаружил, что событие хранилища localStore — это демон, ха-ха.


Возвращаясь к теме, собственно, в случае нормальных запасов знаний, какие решения мы придумаем?

Забудьте следующее:

  1. Каждый опрос или длинный опрос сервера
  2. В соответствии с политикой одного и того же происхождения одна сторона принадлежит другой стороне.opener

Демо и исходный код

Демонстрация многостраничного общения, для нормальной работы откройте его в последней версии браузера Chrome.
Адрес исходного кода демо

Связь между двумя браузерами Windows

WebSocket

Этому не так много объяснений, WebSocket — это протокол, предоставляемый HTML5 для полнодуплексной связи по одному TCP-соединению. Конечно, есть цена, и сервер нужно поддерживать.
js, который сейчас, конечно, более зрелый и стабильныйsocket.ioа такжеws, Есть также легкиеClusterWS.

ты сможешьThe WebSocket API (WebSockets) Узнайте больше о веб-сокетах.

Таймер + клиентское хранилище

Таймер: setTimeout/setInterval/requestAnimationFrame
Хранилище клиента: cookie/localStorage/sessionStorage/indexDB/файловая система Chrome.

О таймерах и о клиентской памяти сказать особо нечего.

  • cookie: Будет приноситься на сервер каждый раз, и хранилище не большое, 4кб?не очень четко помню
  • localStorage/sessionStorage должен быть 5 МБ, sessionStorage попрощается с вами после закрытия браузера.
  • indexDB мощная штука, но чтение асинхронное, и он также может хранить файлы Blob, что действительно много.
  • файловая система хрома,Filesystem & FileWriter API, в основном поддержка хрома и оперы. Эта штука — файловая система.

postMessage

Cross-document messagingУровень одобрения этой штуки составляет 98,9%. Кажется, он может отправлять файлы, ха-ха, мощно.
Но присмотритесь к window.postMessage(), и вам суждено сначала получить объект окна. Ему также суждено быть ограниченным в его использовании, и эти две формы должны быть связаны. Распространенные способы установления контакта:

  • window.open
  • window.opener
  • iframe

Ссылаясь на вышеупомянутый window.open, после открытия вы можете получить дескриптор открытого окна и, конечно же, вы можете напрямую манипулировать окном.


Здесь я думаю, что общий интерфейсный персонал может думать, что программ должно быть выше трех.
Конечно же, поговорим о трех других способах, которые могут быть не так распространены.

StorageEvent

Page 1

localStorage.setItem('message',JSON.stringify({
    message: '消息',
    from: 'Page 1',
    date: Date.now()
}))

Page 2

window.addEventListener("storage", function(e) {
    console.log(e.key, e.newValue, e.oldValue)
});

Как и выше, страница 1 устанавливает сообщение, страница 2 регистрирует событие хранения, и вы можете отслеживать изменения данных.

е вышеStorageEvent, имеет следующие уникальные свойства (все только для чтения):

  • key : Представляет, что имя свойства изменилось. При очистке методом clear() все имена свойств становятся нулевыми.
  • newValue: новое добавленное значение. Значение равно null, если был выполнен метод clear() или имя ключа было удалено.
  • oldValue: Исходное значение. Если был выполнен метод clear() или начальное значение не установлено до того, как будет установлено новое значение, будет возвращено значение null.
  • storageArea: управляемый объект хранилища
  • url: URL-адрес документа, в котором находится объект, ключ которого изменился

Broadcast Channel

Эта штука в основном используется для многооконности, можно использовать и Service Worker. Его поддерживают Firefox, Chrome и Opera. Иногда я действительно ненавижу Safari. Браузер поддерживает около 77%.

Его также очень просто использовать, создать BroadcastChannel, а затем прослушивать события. Только нужно обратить внимание на один момент, название канала должно быть одинаковым.
Page 1

    var channel = new BroadcastChannel("channel-BroadcastChannel");
    channel.postMessage('Hello, BroadcastChannel!')

Page 2

    var channel = new BroadcastChannel("channel-BroadcastChannel");
    channel.addEventListener("message", function(ev) {
        console.log(ev.data)
    });

SharedWorker

Это общий Worker после Web Worker, который может использоваться разными страницами.
MDN дает более полный пример здесьsimple-shared-worker.

Вот эпизод, Safari имеет несколько версий, которые поддерживают эту функцию, а потом нет, это все еще ваш Safari, это действительно 6.

Хотя собственные ресурсы SharedWorker являются общими, но чтобы добиться многостраничного общения друг с другом, ему все же нужно проделать некоторые хитрости. Давайте посмотрим на код самого ShareWoker на примере, предоставленном MDN:

onconnect = function(e) {
  var port = e.ports[0];

  port.onmessage = function(e) {
    var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
    port.postMessage(workerResult);
  }

}

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

var portList = [];

onconnect = function(e) {
  var port = e.ports[0];
  ensurePorts(port);
  port.onmessage = function(e) {
    var data = e.data;
    disptach(port, data);
  };
  port.start();
};

function ensurePorts(port) {
  if (portList.indexOf(port) < 0) {
    portList.push(port);
  }
}

function disptach(selfPort, data) {
  portList
    .filter(port => selfPort !== port)
    .forEach(port => port.postMessage(data));
}

MessageChannel

API обмена сообщениями каналаMessageChannelИнтерфейс позволяет нам создать новый канал сообщений и передать два егоMessagePortсвойство для отправки данных.

Сначала необходимо установить соединение через postMessage.

Основное использование MessageChannel:

var channel = new MessageChannel();
var para = document.querySelector('p');

var ifr = document.querySelector('iframe');
var otherWindow = ifr.contentWindow;

ifr.addEventListener("load", iframeLoaded, false);

function iframeLoaded() {
  otherWindow.postMessage('Hello from the main page!', '*', [channel.port2]);
}

channel.port1.onmessage = handleMessage;
function handleMessage(e) {
  para.innerHTML = e.data;
}   

Что касается онлайн-примера, у MDN официально есть версияСвязь по каналу сообщений

напиши в конце

Если вы считаете, что это хорошо, ваши лайки и комментарии — самая большая мотивация для меня двигаться вперед.

Цитировать

MDN Web Docs - Broadcast Channel
BroadcastChannel | Can I Use
broadcast-channel
StorageEvent
SharedWorker
simple-shared-worker
SharedWorker | Can I Use
Общий поток
feature-shared-web-workers Сводка связи между двумя окнами браузера