javascript - 在页面和 iframe 之间双向使用 MessageChannel() 发送多条消息

标签 javascript iframe message-channel

我正在使用 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; 
  }

我正在通过parentPort运行从iframe到父级的所有后续通信:

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

尽管文档声明消息 channel 是一次性通信,但这似乎有效并且使发起通信变得方便。

我的问题 - 这是受支持的功能还是我在利用未定义的行为?

Here is the source.

编辑 - 我一定误解了示例的意图 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 = '';
    }
  }

这在 Kaiido 的 Plunker 示例中进行了重构。

最佳答案

这并不是很清楚你在做什么,甚至在 github 上阅读你的代码......

您似乎混淆了 WindowObject.postMessage 方法和 MessagePort 方法。 WindowObject 只能在协商部分使用一次。
因此,让我们退一步来更基本地解释应该如何理解事物:

<小时/>

您应该将消息 channel 视为 Yoghurt-pot Telephone® [pdf]

                   –––––                         –––––
                po(r)t1 |~~~~~~~~~~~~~~~~~~~~~~~| po(r)t2
                   –––––                         –––––
  • 必须由一个用户创建它。
  • 然后他会将其中一个积分给予(转移)给其他用户。
  • 完成此操作后,每个用户只能访问自己的点。
  • 因此,为了能够接收来自其他用户的消息,他们必须倾听自己的观点(附加事件处理程序)。
  • 为了发送消息,他们会在他们仍然拥有的唯一位置内说出消息 (postMessage),与他们正在收听的内容相同。
<小时/>

因此要添加一些代码行,您应该做的是:

  1. 生成酸奶 jar 电话®又名消息 channel 。

    var yoghurt_phone = new MessageChannel();
    
  2. 保留其中一个点并将另一个提供给其他用户 (iframe)。为此,我们使用 WindowObject.postMessage 方法,该方法与我们用于通过 MessagePort 进行通信的方法不同

    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. 从框架上接收 PO(R)T 并将其拉紧。

    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。因此,在两端,您需要在自己的单个点上设置监听器。

    // from main doc
    mains_yoghurt_pot.onmessage = frameTalksToMe;
    

    // from iframe doc
    frames_yoghurt_pot.onmessage = mainTalksToMe;
    
  5. 然后,当两个用户中的一个想要告诉另一个用户某件事时,他们会从自己的观点开始。

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

    // or from iframe doc
    frames_yoghurt_pot.postMessage('hello main');
    
<小时/>

Fixed OP's code as a plunker.

关于javascript - 在页面和 iframe 之间双向使用 MessageChannel() 发送多条消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51201120/

相关文章:

javascript - 尝试访问 json 数组中的嵌套项目

javascript - WinJS Promise 然后出错

javascript - 在回调中无法看到父函数中的变量

javascript - 如何制作按钮/链接以在 &lt;iframe&gt; 而不是页面中显示源代码?

python - Selenium - 获取页面中的所有 iframe(甚至是嵌套的)?

javascript - 在iframe中显示之前使用javascript检测url是否存在

javascript - 卡在 postMessage 和 MessageChannel

javascript - Backbone 不会将 URL 写入浏览器历史记录