代码之家  ›  专栏  ›  技术社区  ›  jchristof

对页面和iframe之间的多条消息双向使用MessageChannel()

  •  0
  • jchristof  · 技术社区  · 8 年前

    我使用MessageChannel()在页面和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});
    

    即使文档中声明消息通道是一次性通信,但这似乎起作用,并使启动通信变得方便。

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

    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 = '';
        }
      }
    

    这在kaido的plunker示例中进行了重构。

    1 回复  |  直到 8 年前
        1
  •  7
  •   Kaiido    8 年前

    这并不是很清楚你在做什么,即使是在github上阅读你的代码…

    您似乎混淆了windowobject.postmessage方法和messageport方法。在协商部分,windowobject的只能使用一次。
    所以让我们退一步,更基本地解释一下应该如何理解事情:


    你应该把信息渠道看作 Yoghurt-pot Telephone® [pdf] 是的。

                       –––––                         –––––
                    po(r)t1 |~~~~~~~~~~~~~~~~~~~~~~~| po(r)t2
                       –––––                         –––––
    
    • 一个用户必须创建它。
    • 然后他会给( 转移 )其中一个订单发送给另一个用户。
    • 完成后,每个用户只能访问自己的po(r)t。
    • 因此,为了能够接收来自其他用户的消息,他们必须将耳朵放在自己的po(r)t(附加一个事件处理程序)上。
    • 为了发送信息,他们会说( 邮件 )在他们唯一的宝藏里,还有他们正在听的。

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

    1. 生成 酸奶罐电话 也就是消息频道。

      var yoghurt_phone = new MessageChannel();
      
    2. 保留其中一个po(r)t并将另一个给另一个用户(iframe)。为此,我们使用windowobject。 邮件 方法, 这与我们将用于通过消息端口进行通信的端口不同 是的。

      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。因此,在两端,您需要在自己的单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.