window 消息事件有时触发不止一次
window message Event firing more than one time sometime
我的页面中有一个 IFrame。我正在使用 postmessage 在父页面和子页面的脚本之间建立通信。我还有一个 polar 来反映 Iframe 在所有使用 cookie 的选项卡中最小化和最大化状态。
但问题是我有一个计数器,当我的子页面发送带有特殊对象的消息时,它实际上会增加。但是消息事件在父页面中触发了不止一次。如果它触发不止一次,计数器就会出错。这种情况不会一直发生。有时它工作得很好,有时却不行。跟极地有关系吗?因为当我对此发表评论时,一切正常。
这是听众
function listenIframe() {
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
if (e.data == xyz) {
close();
} else if (e.data == abcd) {
//increase Count;
}
}, false);
}
这是轮询器
function fn(start) {
var x, y, z;
if (start) {
j.k= setTimeout(function stateChangePollar() {
// show or hide logic here
setTimeout(stateChangePollar, 1000);
}, 1000);
}
else {
clearTimeout(j.k);
}
}
你的 listenIframe
什么时候来电?难道是被调用了多次?最好的方法是确保它只被调用一次,否则一个解决方案是将一些东西存储在外部变量中以检查它,如下所示:
let isListenerAttached = false;
function listenIframe() {
if (isListenerAttached) return;
isListenerAttached = true;
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
if (e.data == xyz) {
close();
} else if (e.data == abcd) {
//increase Count;
}
}, false);
}
虽然这不是最佳解决方案,但使用外部变量处理它很容易变得混乱。特别是如果它是一个全局变量。最好的解决方案是确保 listenIframe
只被调用一次。
这可能是因为 addEventListener
调用了不止一次,很可能是在循环中或在不同的文件中。
事实上,每次调用 addEventListener
方法时,都会有一个新的处理函数附加到事件堆栈,并在事件触发时执行。
假设您对 window
对象的 resize
事件感兴趣:
function resizeHandler(e) {
console.log("Window is resized");
}
window.addEventListener("resize", resizeHandler);
window.addEventListener("resize", resizeHandler);
如果现在调整 window 的大小,您将在控制台中看到:
Window is resized
Window is resized
因此,乍一看似乎事件被调用了多次,而事实是事件只被调用了一次,但多个处理程序正在侦听该事件。
您可以通过确保在您的代码中只有一个 addEventListener
用于该特定事件来解决此问题。
我的页面中有一个 IFrame。我正在使用 postmessage 在父页面和子页面的脚本之间建立通信。我还有一个 polar 来反映 Iframe 在所有使用 cookie 的选项卡中最小化和最大化状态。
但问题是我有一个计数器,当我的子页面发送带有特殊对象的消息时,它实际上会增加。但是消息事件在父页面中触发了不止一次。如果它触发不止一次,计数器就会出错。这种情况不会一直发生。有时它工作得很好,有时却不行。跟极地有关系吗?因为当我对此发表评论时,一切正常。
这是听众
function listenIframe() {
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
if (e.data == xyz) {
close();
} else if (e.data == abcd) {
//increase Count;
}
}, false);
}
这是轮询器
function fn(start) {
var x, y, z;
if (start) {
j.k= setTimeout(function stateChangePollar() {
// show or hide logic here
setTimeout(stateChangePollar, 1000);
}, 1000);
}
else {
clearTimeout(j.k);
}
}
你的 listenIframe
什么时候来电?难道是被调用了多次?最好的方法是确保它只被调用一次,否则一个解决方案是将一些东西存储在外部变量中以检查它,如下所示:
let isListenerAttached = false;
function listenIframe() {
if (isListenerAttached) return;
isListenerAttached = true;
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
if (e.data == xyz) {
close();
} else if (e.data == abcd) {
//increase Count;
}
}, false);
}
虽然这不是最佳解决方案,但使用外部变量处理它很容易变得混乱。特别是如果它是一个全局变量。最好的解决方案是确保 listenIframe
只被调用一次。
这可能是因为 addEventListener
调用了不止一次,很可能是在循环中或在不同的文件中。
事实上,每次调用 addEventListener
方法时,都会有一个新的处理函数附加到事件堆栈,并在事件触发时执行。
假设您对 window
对象的 resize
事件感兴趣:
function resizeHandler(e) {
console.log("Window is resized");
}
window.addEventListener("resize", resizeHandler);
window.addEventListener("resize", resizeHandler);
如果现在调整 window 的大小,您将在控制台中看到:
Window is resized
Window is resized
因此,乍一看似乎事件被调用了多次,而事实是事件只被调用了一次,但多个处理程序正在侦听该事件。
您可以通过确保在您的代码中只有一个 addEventListener
用于该特定事件来解决此问题。