Spec-Zone.ru › Web APIs

Использование канальной передачи сообщений

Примечание: Эта функция доступна в Потоках выполнения JavaScript.

API канальной передачи сообщений позволяет двум отдельным скриптам, выполняющимся в разных контекстах просмотра, прикреплённых к одному документу (например, два элемента <iframe>, основной документ и одиночный <iframe>, или два документа через SharedWorker) обмениваться сообщениями напрямую через двунаправленные каналы (или трубы) с портом на каждом конце.

В этой статье мы рассмотрим основы использования этой технологии.

Сферы применения

Канальная передача сообщений полезна в основном в тех случаях, когда у вас есть социальный сайт, который встраивает возможности других сайтов в свой главный интерфейс через фреймы, такие как игры, адресные книги или проигрыватель аудио с персонализированным выбором музыки. Когда эти компоненты действуют как автономные единицы, всё нормально, но сложность возникает, когда вам нужна взаимосвязь между основным сайтом и элементами <iframe>, или между разными элементами <iframe>. Например, что если вы захотите добавить контакт в адресную книгу с основного сайта, добавить высокие баллы из игры в свой профиль, или добавить новые фоновые музыкальные композиции из проигрывателя в игру? Такие вещи не так легко сделать с использованием обычных веб-технологий, из-за используемых веб-моделей безопасности. Вам нужно подумать о том, доверяют ли источники друг другу, и как передаются сообщения.

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

Примечание: Для получения дополнительной информации и идей, раздел Порты в качестве основы модели объектных возможностей в веб-среде спецификации будет полезен для чтения.

Простые примеры

Чтобы помочь вам начать, мы опубликовали несколько демо-версий на GitHub. Во-первых, ознакомьтесь с нашей демо-версией канальной передачи сообщений (запустить её онлайн), которая демонстрирует очень простую передачу одного сообщения между страницей и встроенным <iframe>.

Во-вторых, посмотрите нашу демо-версию с множественными сообщениями (запустить её онлайн), которая демонстрирует немного более сложную настройку, позволяющую отправлять несколько сообщений между основной страницей и IFrame.

В этой статье мы будем фокусироваться на последнем примере, который выглядит так:

Demo with "Hello this is my demo" sent as five separate messages. The messages are displayed as a bulleted list.

Создание канала

На основной странице демо-версии у нас простая форма с текстовым полем для ввода сообщений, которые будут отправлены в <iframe>. Также у нас есть абзац, который мы будем использовать позднее для отображения подтверждающих сообщений, которые мы получим обратно от <iframe>.

const input = document.getElementById("message-input");
const output = document.getElementById("message-output");
const button = document.querySelector("button");
const iframe = document.querySelector("iframe");

const channel = new MessageChannel();
const port1 = channel.port1;

// Wait for the iframe to load
iframe.addEventListener("load", onLoad);

function onLoad() {
  // Listen for button clicks
  button.addEventListener("click", onClick);

  // Listen for messages on port1
  port1.onmessage = onMessage;

  // Transfer port2 to the iframe
  iframe.contentWindow.postMessage("init", "*", [channel.port2]);
}

// Post a message on port1 when the button is clicked
function onClick(e) {
  e.preventDefault();
  port1.postMessage(input.value);
}

// Handle messages received on port1
function onMessage(e) {
  output.innerHTML = e.data;
  input.value = "";
}

Мы начинаем с создания нового канала сообщений, используя конструктор MessageChannel().

Когда IFrame загрузится, мы регистрируем обработчик onclick для нашей кнопки и обработчик onmessage для MessageChannel.port1. Наконец, мы передаём MessageChannel.port2 в IFrame, используя метод window.postMessage.

Давайте разберёмся, как работает строка iframe.contentWindow.postMessage более подробно. Она принимает три аргумента:

  1. Отправляемое сообщение. Для первоначальной передачи порта это сообщение может быть пустой строкой, но в этом примере оно установлено на 'init'.
  2. Источник, которому должно быть отправлено сообщение. * означает «любой источник».
  3. Объект, владение которым передаётся принимающему контексту просмотра. В данном случае, мы передаём MessageChannel.port2 в IFrame, чтобы он мог использоваться для связи с основной страницей.

При нажатии на нашу кнопку, мы предотвращаем стандартную отправку формы, а затем отправляем значение, введённое в наше текстовое поле, в IFrame через MessageChannel.

Получение порта и сообщения во фрейме

В элементах <iframe> у нас есть следующий JavaScript:

const list = document.querySelector("ul");
let port2;

// Listen for the initial port transfer message
window.addEventListener("message", initPort);

// Setup the transferred port
function initPort(e) {
  port2 = e.ports[0];
  port2.onmessage = onMessage;
}

// Handle messages received on port2
function onMessage(e) {
  const listItem = document.createElement("li");
  listItem.textContent = e.data;
  list.appendChild(listItem);
  port2.postMessage(`Message received by IFrame: "${e.data}"`);
}

Когда первоначальное сообщение получено с основной страницы через метод window.postMessage, выполняется функция initPort. Это сохраняет переданный порт и регистрирует обработчик onmessage, который будет вызываться каждый раз, когда сообщение передаётся через наш MessageChannel.

Когда сообщение получено с основной страницы, мы создаём элемент списка и вставляем его в неупорядоченный список, устанавливая значение textContent элемента списка равным атрибуту data события (в нём содержится фактическое сообщение).

Далее, мы отправляем подтверждающее сообщение обратно на главную страницу через канал сообщений, вызвав MessagePort.postMessage у MessageChannel.port2, который был первоначально передан во фрейм.

Получение подтверждения на основной странице

Вернёмся к основной странице и рассмотрим функцию обработчика onmessage.

// Handle messages received on port1
function onMessage(e) {
  output.innerHTML = e.data;
  input.value = "";
}

Когда подтверждающее сообщение получено обратно от IFrame о том, что исходное сообщение было успешно получено, это выводит подтверждение в абзац и очищает текстовое поле, чтобы можно было отправить следующее сообщение.

Спецификации

Спецификация
HTML
# каналы-сообщений
HTML
# порты-сообщений

Совместимость с браузерами

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari на iOS Samsung Internet WebView Android
Using_channel_messaging 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
close 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
message_event 2 12 41 10.6 5 18 41 11.5 4.2 1.0 ≤37
messageerror_event 60 18 57 47 16.4 60 57 47 16.4 8.0 60
postMessage 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
start 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
worker_support 4 12 41 ≤15 5 18 41 ≤14 4.2 1.0 ≤37
END_OF_DOCUMENT_MARKER
Рабочий стол Мобильный
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на IOS Samsung Internet WebView Android
MessageChannel 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
Using_channel_messaging 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
port1 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4
port2 2 12 41 10.6 5 18 41 11 4.2 1.0 4.4

api.КаналСообщений

Таблицы BCD загружаются только в браузере

api.ПортСообщений

Таблицы BCD загружаются только в браузере

См. также

  • API обмена сообщениями канала
  • API веб-рабочих потоков
  • API канала широковещательной передачи

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API