微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 JavaScript“window.postMessage”会创建重复的消息?

如何解决为什么 JavaScript“window.postMessage”会创建重复的消息?

我正在尝试打开一个弹出窗口,做一些事情,然后向打开的窗口发送一条消息,以便我可以用它发送的数据做更多的事情。

基本上,我正在适应 the process outlined here

这是我在“打开窗口”上的代码。它在点击社交连接按钮时运行。代码打开一个弹出窗口,并在打开窗口上分配一个监听事件来接收来自弹出窗口的消息:

//Do the operation
let windowObjectReference = null;
let prevIoUsUrl = null;

const openSignInWindow = (url,name) => {

    // remove any existing event listeners
    window.removeEventListener('message',receiveMessage);

    // window features
    const strWindowFeatures =
        'toolbar=no,menubar=no,width=600,height=700,top=100,left=100';

    if (windowObjectReference === null || windowObjectReference.closed) {
        /* if the pointer to the window object in memory does not exist
         or if such pointer exists but the window was closed */
        windowObjectReference = window.open(url,name,strWindowFeatures);
    } else if (prevIoUsUrl !== url) {
        /* if the resource to load is different,then we load it in the already opened secondary window and then
         we bring such window back on top/in front of its parent window. */
        windowObjectReference = window.open(url,strWindowFeatures);
        windowObjectReference.focus();
    } else {
        /* else the window reference must exist and the window
         is not closed; therefore,we can bring it back on top of any other
         window with the focus() method. There would be no need to re-create
         the window or to reload the referenced resource. */
        windowObjectReference.focus();
    }

    // add the listener for receiving a message from the popup
    window.addEventListener('message',event => receiveMessage(event),false);

    // assign the prevIoUs URL
    prevIoUsUrl = url;

};


const receiveMessage = event => {
    // Do we trust the sender of this message? (might be different from what we originally opened,for example).
    if (event.origin !== websiteHomeUrlNoSlash) {
        return;
    }

    const { data } = event;
    console.log(data); //<--- THIS WHERE I'm SEEING DUPLICATES

};

//Invoke the function
openSignInWindow(url,name);

在弹出窗口中,用户登录到他们的社交帐户,然后被重定向到我的应用程序上运行以下代码页面代码将消息发送回打开的窗口,然后关闭弹出窗口:

// Get the message data
const messageObj = {
    pluginReason: pluginReasonVar,displayName: displayNameVar,provider: providerVar,};

if (window.opener) {
    // send them to the opening window
    window.opener.postMessage(messageObj,websiteHomeUrlNoSlash);
    // close the popup
    if (closePopup) {
        window.close();
    }
}

一切几乎都按预期工作。用户可以登录他们的社交帐户,并且弹出窗口的所有重定向和打开和关闭都正常工作。

问题:

如果用户在没有刷新页面的情况下多次执行 Social Connect 流程,那么每次运行都会越来越多地复制打印到控制台的消息数据。

例如:

  • 在第一次运行时,console.log(data) 被打印一次。到目前为止,这按预期工作。
  • 在第二次运行时 console.log(data) 打印两次。它应该只打印一次。
  • 在第 3 次运行时 console.log(data) 打印了 3 次。它应该只打印一次。

每次运行社交连接过程时,它应该只打印一次。但不知何故,它会在每次后续运行中添加一个重复的副本。

这种重复不断增加,直到用户刷新页面,从一开始计数。

我想在 console.log(data) 处进行更多的数据操作,但在每次后续运行时都会创建重复副本时我无法这样做。

我如何阻止这种情况发生?

也许是因为监听器事件没有分离?如果是这样,我该如何解决

解决方法

您创建了一个匿名方法 (event) => { } 作为包装器并将其附加到 addEventListener 方法。

window.addEventListener('message',event => receiveMessage(event),false);

无法删除

window.removeEventListener('message',receiveMessage);

要修复它,请进行如下更改:

window.addEventListener('message',receiveMessage,false);

同时,如果每次关闭窗口时 receiveMessage 方法都会丢失,最好将 removeEventListener 部分移到 receiveMessage 内。

const receiveMessage = (event)=> {
  window.removeEventListener('message',receiveMessage);
  // do something else
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。