Использование MessageChannel () для направления нескольких сообщений между страницей и iframe - PullRequest
0 голосов
/ 06 июля 2018

Я использую MessageChannel () для передачи сообщений между страницей и iframe. В моем сценарии iframe является инициатором связи, и страница, содержащая его, получает, преобразует и отвечает на iframe.

Поскольку я внедрял систему, я сначала взял и сохранил ссылку на порт, переданный в iframe, кэшировал его и продолжаю использовать его для каждой последующей связи.

IFrame:

 window.onmessage = (e) => {
    console.log("iframe port established");
    //using this port for all following communications
    parentPort = e.ports[0];
    onmessage = establishedConnectionHandler; 
  }

Я запускаю все последующие сообщения от iframe до родителя через parentPort:

parentPort.postMessage({command, guid, message});

, несмотря на то, что в документах указано, что канал сообщений является однократным обменом данными, это работает и делает инициирование обмена данными удобным.

Мой вопрос - это поддерживаемая функциональность или я использую неопределенное поведение?

Вот источник.

Редактировать - я, должно быть, неправильно понял цель примера MDN :

button.onclick = function(e) {
    e.preventDefault();

    var channel = new MessageChannel();
    otherWindow.postMessage(textInput.value, '*', [channel.port2]);

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

Это рефакторинг в примере с Кайидо Плункер.

1 Ответ

0 голосов
/ 06 июля 2018

Не совсем понятно, что вы делаете, даже читая ваш код на github ...

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


Вы должны думать о каналах сообщений как о Йогуртовый телефон® [pdf] .

                   –––––                         –––––
                po(r)t1 |~~~~~~~~~~~~~~~~~~~~~~~| po(r)t2
                   –––––                         –––––
  • Один пользователь должен создать его.
  • Затем он передаст ( передача ) один из по (т) другим пользователям.
  • Как только это будет сделано, каждый пользователь будет иметь доступ только к своему собственному po (r) t.
  • Таким образом, чтобы иметь возможность получать сообщения от другого пользователя, он должен приложить ухо к своему собственному po (r) t (прикрепить обработчик события).
  • А чтобы отправлять сообщения, они будут произносить сообщение ( postMessage ) внутри единственного po (r) t, которое у них еще есть, то же самое, что они слушают.

Итак, чтобы добавить несколько строк кода, вам нужно сделать следующее:

  1. Генерируйте Телефон для йогуртовой посуды® a.k.a MessageChannel.

    var yoghurt_phone = new MessageChannel();
    
  2. Сохраните один из ключей и передайте другой другому пользователю (iframe). Для этого мы используем метод WindowObject. postMessage , , который отличается от того, который мы будем использовать для связи через MessagePorts .

    mains_yoghurt_pot = yoghurt_phone.port1;
    frame.contentWindow.postMessage( // this is like a physical meeting
      'look I made a cool Yoghurt-phone', // some useless message
      '*', // show your id?
      [yoghurt_phone.port2] // TRANSFER the po(r)t
    ); 
    
  3. Из рамы возьмите рывок и держите его крепко.

    window.onmessage = function physicalMeeting(evt) {
      if(evt.ports && evt.ports.length) { // only if we have been given a po(r)t
        frames_yoghurt_pot = evt.ports[0];
        // ... 
    
  4. С этого момента каждый пользователь имеет свой собственный po (r) t и только один po (r) t. Таким образом, на обоих концах вам нужно настроить слушателей на их собственный po (r) t.

    // from main doc
    mains_yoghurt_pot.onmessage = frameTalksToMe;
    

    // from iframe doc
    frames_yoghurt_pot.onmessage = mainTalksToMe;
    
  5. И затем, когда один из двух пользователей хочет что-то сказать другому, он будет делать с свои собственные po (r) t .

    // from main doc
    mains_yoghurt_pot.postMessage('hello frame');
    

    // or from iframe doc
    frames_yoghurt_pot.postMessage('hello main');
    

Исправлен код ОП в качестве плункера.

...