admin管理员组文章数量:1322517
I'm trying to open a popup window, do some stuff, and send a message back to the opening window so I can do some more stuff with the data it sends.
Essentially, I'm adapting the process outlined here.
This is my code on the "opening window". It runs when a social connect button is clicked. The code opens a popup window and assigns a listener event on the opening window to receive a message from the popup:
//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);
In the popup users login to their social account and then get redirected to a page on my app where the below code is run. The code posts a message back to the opening window and then closes the popup:
// 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();
}
}
Everything almost works as expected. Users can login to their social accounts and all the redirections and opening and closing of the popup works fine.
The Problem:
If users go through the Social Connect process multiple times without refreshing the page, then the message data that is printed to the console is duplicated more and more each run.
For example:
- On the 1st run
console.log(data)
is printed once. So far this works as expected. - On the 2nd run
console.log(data)
prints twice. It should only be printed once. - On the 3rd run
console.log(data)
prints three times. It should only be printed once.
Each time the Social Connect process is run it should only print once. But somehow it's adding a duplicate copy on each subsequent run.
This duplication keeps growing until the users refreshes the page, which starts the count back at one.
I want to do more data manipulation at the point of the console.log(data)
but I can't do that while it's creating duplicates copies on each subsequent run.
How do I stop that from happening?
Maybe it's because the listener event is not detaching? If so, how do I fix that?
I'm trying to open a popup window, do some stuff, and send a message back to the opening window so I can do some more stuff with the data it sends.
Essentially, I'm adapting the process outlined here.
This is my code on the "opening window". It runs when a social connect button is clicked. The code opens a popup window and assigns a listener event on the opening window to receive a message from the popup:
//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);
In the popup users login to their social account and then get redirected to a page on my app where the below code is run. The code posts a message back to the opening window and then closes the popup:
// 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();
}
}
Everything almost works as expected. Users can login to their social accounts and all the redirections and opening and closing of the popup works fine.
The Problem:
If users go through the Social Connect process multiple times without refreshing the page, then the message data that is printed to the console is duplicated more and more each run.
For example:
- On the 1st run
console.log(data)
is printed once. So far this works as expected. - On the 2nd run
console.log(data)
prints twice. It should only be printed once. - On the 3rd run
console.log(data)
prints three times. It should only be printed once.
Each time the Social Connect process is run it should only print once. But somehow it's adding a duplicate copy on each subsequent run.
This duplication keeps growing until the users refreshes the page, which starts the count back at one.
I want to do more data manipulation at the point of the console.log(data)
but I can't do that while it's creating duplicates copies on each subsequent run.
How do I stop that from happening?
Maybe it's because the listener event is not detaching? If so, how do I fix that?
Share Improve this question edited Jan 13, 2021 at 6:31 TinyTiger asked Jan 13, 2021 at 3:14 TinyTigerTinyTiger 2,11112 gold badges65 silver badges131 bronze badges 4- 1 I think you just need to {EventTarget}.removeEventListener() after the window close. otherwise you duplicate the listeners – Shir Gans Commented Jan 13, 2021 at 3:28
-
The event listener is on the opening window, not the popup. Trying to remove it from the popup (where
window.close();
sits) just throws a ReferenceError because no event listener is defined on that window. Also I've already added awindow.removeEventListener('message', receiveMessage);
to the opening window. You can find it on the first line insideopenSignInWindow
. That should remove any existing event listeners on the opening window. Maybe the problem isn't the event listener not detaching but something else? – TinyTiger Commented Jan 13, 2021 at 5:29 - Consider using developer.mozilla/en-US/docs/Web/API/Broadcast_Channel_API instead of the postMessage api, your problem will then go away by itself. See stackoverflow./a/53876900/2494754 – NVRM Commented Jan 13, 2021 at 5:56
- Thanks but browser support for Broadcast Channel is 76.26% (caniuse./broadcastchannel) while Post Message is 96.29% (caniuse./mdn-api_window_postmessage). So in this case I need to go with Post Message because it has better support. – TinyTiger Commented Jan 13, 2021 at 6:02
1 Answer
Reset to default 8You have created an anonymous method (event) => { }
as a wrapper and attached it to the addEventListener
method.
window.addEventListener('message', event => receiveMessage(event), false);
It can't be removed by
window.removeEventListener('message', receiveMessage);
To fix it, make changes like this:
window.addEventListener('message', receiveMessage, false);
Meanwhile, if the method receiveMessage
gets lost every time the window has been closed, it's better to move the removeEventListener
part inside the receiveMessage
.
const receiveMessage = (event)=> {
window.removeEventListener('message', receiveMessage);
// do something else
}
本文标签: popupwindowWhy does JavaScript quotwindowpostMessagequot create duplicate messagesStack Overflow
版权声明:本文标题:popupwindow - Why does JavaScript "window.postMessage" create duplicate messages? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742110220a2421216.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论