为什么JavaScript;window.postMessage“;创建重复消息?
我正在尝试打开一个弹出窗口,做一些事情,然后将消息发送回打开的窗口,这样我就可以用它发送的数据做更多的事情 基本上,我正在适应 这是我在“打开窗口”上的代码。单击“社交连接”按钮时,它将运行。该代码打开一个弹出窗口,并在打开窗口上分配一个侦听器事件,以接收来自弹出窗口的消息:为什么JavaScript;window.postMessage“;创建重复消息?,javascript,popupwindow,Javascript,Popupwindow,我正在尝试打开一个弹出窗口,做一些事情,然后将消息发送回打开的窗口,这样我就可以用它发送的数据做更多的事情 基本上,我正在适应 这是我在“打开窗口”上的代码。单击“社交连接”按钮时,它将运行。该代码打开一个弹出窗口,并在打开窗口上分配一个侦听器事件,以接收来自弹出窗口的消息: //Do the operation let windowObjectReference = null; let previousUrl = null; const openSignInWindow = (url, na
//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, name, 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();
}
}
一切都像预期的那样。用户可以登录到他们的社交帐户,所有的重定向和弹出窗口的打开和关闭都可以正常工作
问题:
如果用户多次执行社交连接过程而没有刷新页面,则每次运行时打印到控制台的消息数据会越来越多地重复
例如:
- 在第一次运行控制台时,日志(数据)打印一次。到目前为止,这是预期的效果
- 在第二次运行时,
打印两次。它只能打印一次console.log(数据)
- 在第三次运行时,
打印三次。它只能打印一次console.log(数据)
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
}
我认为您只需要在窗口关闭后{EventTarget}.removeEventListener()。否则将复制侦听器事件侦听器位于打开的窗口上,而不是弹出窗口上。试图将其从弹出窗口(其中
window.close();
所在位置)中删除时,只会抛出一个ReferenceError,因为该窗口上没有定义事件侦听器。另外,我已经添加了一个窗口代码>到打开的窗口。您可以在openSignInWindow
的第一行找到它。这将删除打开窗口上的任何现有事件侦听器。也许问题不是事件侦听器没有分离,而是别的什么吗?考虑使用而不是PASSMEST API,你的问题就会自行消失。请参见“谢谢”,但广播频道的浏览器支持率为76.26%(),而发布消息的浏览器支持率为96.29%()。所以在这种情况下,我需要使用Post消息,因为它有更好的支持。我已经注释掉了window.addEventListener('Message',event=>receiveMessage(event),false)代码>内部openSignInWindow
并将其替换为窗口。addEventListener('message',receiveMessage,false)代码>。不幸的是,这并没有解决问题,我仍然得到重复的console.log
打印。可能需要一些指导,以确定您希望我在哪里测试window.receiveMessage=()=>{}代码>但是我已经在窗口下测试了它
以及直接位于openSignInWindow(oneAllDirectConnectUrl,windowName)上方的代码>。两个位置仍然存在重复打印的问题。我删除了那个位置,因为我刚刚意识到它是一个不同的窗口
对象。方向是每次启动新窗口时,receiveMessage
都是一个新方法,即使它具有相同的名称。所以我在想,你是否可以将它传入或存储在全局对象中的某个地方,以确保它在每次工作时都是相同的方法。顺便问一下,它是否是放置window.removeEventListener('message',receiveMessage)的一个选项代码>在你的receiveMessage
功能中?开始工作了!我替换了window.addEventListener('message',event=>receiveMessage(event),false)代码>带有窗口。addEventListener('message',receiveMessage,false)代码>如您在回答中建议的,然后我还添加了窗口。removeEventListener('message',receiveMessage)代码>在receivemessage
功能中,如上述注释所示。现在,它每次只打印一个:)如果您编辑您的答案以包含最后一部分,我将标记为已接受。干杯