Решение проблемы с cross-origin postMessage в IE10

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для правильного использования postMessage в IE10 укажите конкретный целевой источник (origin) и проведите проверку источника отправителя. Ваш инструментарий для исправления ситуации выглядит так:

JS
Скопировать код
// Окно отправителя, готовое к общению
window.opener.postMessage('Сообщение', 'https://receiver.example.com');

// Окно получателя, с установленной защитой
window.addEventListener('message', (e) => {
    if (e.origin === 'https://sender.example.com') { // Осторожность не повредит
        console.log(e.data); // ...Отлично, давайте посмотрим, что нам пришло
    }
}, false);
Кинга Идем в IT: пошаговый план для смены профессии

Детальное руководство по работе с postMessage в IE10

Использование MessageChannel в IE10

postMessage обычно работает без сбоев, однако, IE10 иногда может преподнести сюрпризы. API MessageChannel предоставляет структуру, которая надежно функционирует в IE10:

JS
Скопировать код
let channel = new MessageChannel();
let iframe = document.getElementById('myIframe').contentWindow;

// Отправляем сообщение через port2 и ожидаем ответ в port1
channel.port1.onmessage = function(event) { 
    console.log(event.data); // Как есть, без загадок
};
iframe.postMessage('Привет', '*', [channel.port2]); // Отправляем сигнал в космос. Но не забывайте указывать конкретный целевой источник в реалиях продакшена.

Подробную информацию вы найдете в документации MessageChannel на MSDN.

Альтернативный подход с использованием iframe и прокси-страницы

Если MessageChannel кажется вам неуместным, вы можете использовать прокси-страницу на том же домене, где находится отправитель. С помощью продвинутого iframe можно передать сообщение:

JS
Скопировать код
// Создаём элемент iframe просто так
let iframe = document.createElement('iframe');
iframe.src = 'https://proxy.example.com/proxy.html'; // Мы в прямом эфире
document.body.appendChild(iframe);

// В proxy.html
window.addEventListener('message', (e) => {
    if (e.data && e.source) {
        let targetWindow = window.open('', 'targetWindowName'); 
        targetWindow.postMessage(e.data, 'https://target.example.com'); // Сюрпризы продолжаются
    }
});

Регулярная отправка сообщений с помощью setInterval

Желаете наладить стабильный обмен сообщениями? Сочетание функций postMessage и setInterval идеально подойдёт для этой цели:

JS
Скопировать код
setInterval(function() {
    let targetWindow = window.open('', 'targetWindowName'); 
    targetWindow.postMessage('Периодическое сообщение', 'https://target.example.com'); // Тук-тук. Кто там? Еще одно сообщение.
}, 5000); // Точно как по часам, каждые 5 секунд

Убедитесь, что окно-получатель настроено на прием сообщений. И помните о важности проверки источника сообщения!

Пересылка объектов с использованием JSON.stringify()

Не забывайте преобразовывать ваши объекты перед отправкой с помощью JSON.stringify():

JS
Скопировать код
let myBag = { essentials: "packed" };
let targetWindow = window.open('https://target.example.com');
targetWindow.postMessage(JSON.stringify(myBag), '*'); // В путь!

И обратно, после прибытия:

JS
Скопировать код
window.addEventListener('message', (e) => {
    let unpackedBag = JSON.parse(e.data);
    // Здесь доступ к распакованным сокровищам
});

Визуализация

Процесс работы кросс-доменного postMessage в IE10:

Остров A (🏝️ A): отправляет сообщение в бутылке (📩)

Остров B (🏝️ B): ожидает получения сообщения

Ожидание: 🏝️ A 🌊 📩 ➡️ 🌊 🏝️ B

Реальность в IE10: 🏝️ A 🌊 📩 ✖️ 🚫

Распространенные приемы для бесперебойной работы

Обеспечьте совместимость с различными браузерами

postMessage прекрасно работает с новыми браузерами, но всегда делайте перекрестные проверки. Возможно, потребуется добавить проверку методов вроде addEventListener для устаревших браузеров:

JS
Скопировать код
if (window.attachEvent) { // О, те времена, IE8
    window.attachEvent('onmessage', handleMessage);
} else {
    window.addEventListener('message', handleMessage, false);
}

С учетом прошлого: проверяйте отправителя

С postMessage нужно быть настороже. Осторожность никогда не повредит:

JS
Скопировать код
function handleMessage(event) {
    if (event.origin !== 'https://trusted.example.com') {
        // Стоп, не поехали!
        return;
    }
    // Всё идеально, можно продолжить
}

Аккуратно закрывайте окна

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

JS
Скопировать код
let remoteWindow = window.open('https://target.example.com', 'RemoteWindow');
// Диалог завершен...
remoteWindow.close(); // До свидания, Фелиция

Полезные материалы

  1. Window postMessage() – Веб-API | MDN — Инструкции MDN по postMessage.
  2. HTML Living Standard — Официальная спецификация HTML от WHATWG.
  3. "postMessage" на Can I use... — Таблица совместимости браузеров для postMessage.
  4. DOM Exception 12 для window.postMessage – Stack Overflow — Обсуждение проблем и их решений для postMessage.
  5. Способы обхода политики одного происхождения – Stack Overflow — Полезная информация о кросс-доменном обмене информацией.