【发布时间】:2021-11-22 10:54:14
【问题描述】:
我想做什么: 打开一个弹出窗口并在弹出窗口准备好时发送 postMessage。
问题: 我遇到了Race Condition,弹出窗口尚未准备好但已发送消息。我尝试收听“INIT”消息并在弹出窗口中发回消息。但问题是当网络延迟或某些慢速计算机无法收到初始消息时。
setTimeout 显然不是一个好的解决方案
我有问题的代码: 父窗口
const windowFeatures = "height=800,width=1280,toolbar=1,menubar=1,location=1";
const printWindow = window.open("/print", "Print_Me", windowFeatures);
setTimeout(() => {printWindow.postMessage({printPageStatus: "INIT"}, window.origin)}, 1000)
window.addEventListener("message", (event) => {
if(event.origin !== window.origin) return;
if(event.data.printPageStatus === "READY") {
printWindow.postMessage({message: "from parent", window.origin);
return;
}
});
弹出窗口
constructor() {
window.addEventListener("message", event => {
if(event.origin !== window.origin) return;
if(event.data.printPageStatus === "INIT")
this.sendReadyConfirmation(event);
if(event.data.message === "from parent") {
this.processMessages(event.data);
}
}, false);
}
sendReadyConfirmation(e): void {
e.source.postMessage({printPageStatus: "READY"}, e.origin);
}
谢谢
【问题讨论】:
-
您是否尝试改用
sendReadyConfirmationinngOnInit? -
我试过了,对我没用。问题是父母发送的初始消息有竞争条件问题。 setTimeout 更长(如 5 秒)在大多数情况下都可以工作,但这不是一个好的解决方案。
-
我不明白为什么
sendReadyConfirmation在addEventListener中。我大致了解您想要做什么(在发送数据之前等待窗口准备好),但在我看来,只需要sendReadyConfirmation,或者直接在ngOnInit上的constructor。在发送“READY”消息之前监听消息有什么意义? -
这只是试图确认通信正在发生...... Ritesh Waghela 提到使用 onload 和有点工作......我仍然有一些问题
-
window.parent in popup 不起作用.. 我想只适用于 iFrame。因此,在父级中,我向子级弹出窗口发送了“INIT”消息,并让子级确认消息已收到并“就绪”,然后再发送另一条消息。是的,这样做看起来没有意义。但简单地说,如果在弹出窗口中有与父窗口通信的方式,那就太好了。正如下面提到的 Ritesh Waghela,onload 事件将知道何时启动子弹出窗口然后发送消息。它工作得更好,但有时子弹出窗口仍然没有收到消息。带 onload 的 1 秒 setTimeout 将起作用
标签: javascript angular dom-events postmessage