在接收消息 JavaScript 中过滤消息



我正在与JS的postMessage方法建立跨域通信。嵌入式 iframe 正在发送消息,父窗口正在接收消息。问题是,即使在 receivedMessage 中检查了来源(这减少了大量收到的消息数量),我仍然收到两条消息,一条是我发布的,另一条是很久以前为不同目的而写的。因此,我无法真正修改此其他(不需要的)消息的postMessage方法。就此而言,在postMessage方法或receiveMessage中是否有一种方法可以帮助识别哪一个是我的?也许我在这里缺少一些额外的参数或配置?

postMessage 的代码(在嵌入式 iframe 中):

window.parent.postMessage("Hello world!", "*");

接收消息的代码(在父窗口中):

    window.addEventListener("message", receiveMessage, false);
    function receiveMessage(e) {
      var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
      var secureHost = "https" + reliableHost;
      var notSecureHost = "http" + reliableHost;
      if (e.origin.indexOf(secureHost) != -1 || e.origin.indexOf(notSecureHost) != -1) {
        var data = e.data;
        console.log(data);
        console.log(e.source);
      // filter the other event
      }
    }

由于 data 参数完全在您的控制之下,并且可以是一个对象,因此您可以使用 data 参数中的约定来确保只处理您关心的消息。另请注意,indexOf(...) != -1可能不太正确,您可能希望改用indexOf(...) == 0(或startsWith),以避免字符串后面的匹配。

所以在收到时(见***行[你必须用SO的显示屏向右滚动]):

window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
  var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
  var secureHost = "https" + reliableHost;
  var notSecureHost = "http" + reliableHost;
  if ( (e.origin.indexOf(secureHost) == 0 || e.origin.startsWith(notSecureHost) == 0) && // ***
       (e.data && e.data.type === "whatever")                                            // ***
     ) {                                                                                 // ***
    var payload = e.data.payload;                                                        // ***
    console.log(payload);                                                                // ***
    console.log(e.source);
  // filter the other event
  }
}

发送时:

postMessage({type: "whatever", payload: /*...*/});

我总是使用具有不同type值的这种机制,以便与同一整体页面/应用程序进行不同通信的通信渠道相互干扰。

是的:而不是传入字符串,例如 "Hello world!" ,而是传入一个对象,并针对该对象执行检查。您可以先检查e.data是否typeof object,然后检查对象具有哪些属性。您可以设置任何类型的自定义属性,以允许您标识感兴趣的帖子消息。例如,iframe 可以执行以下行:

window.parent.postMessage({
    source: 'my-custom-app',
    message: 'Hello world!'
}, '*');

然后在收到帖子消息时,您可以简单地检查是否:

  1. 发布消息有效负载(即data参数)是一个对象,并且
  2. 发布消息有效负载包含密钥source,其值为 my-custom-app

父页面上的示例代码:

window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
  var reliableHost = "://" + "<%= Site.current_site.internal_admin_host %>";
  var secureHost = "https" + reliableHost;
  var notSecureHost = "http" + reliableHost;
  // Guard clause to catch unwanted messages from other hosts
  if (e.origin.indexOf(secureHost) === -1 && e.origin.indexOf(notSecureHost) === -1)
    return;
  var data = e.data;
  if (typeof data === 'object' && data.source === 'my-custom-app') {
    // Filtered event handling here
  }
}

最新更新