window.postMessage 到 Angular 中的弹出窗口

Posted

技术标签:

【中文标题】window.postMessage 到 Angular 中的弹出窗口【英文标题】:window.postMessage to popups in Angular 【发布时间】: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);
  

谢谢

【问题讨论】:

您是否尝试改用sendReadyConfirmation in ngOnInit 我试过了,对我没用。问题是父母发送的初始消息有竞争条件问题。 setTimeout 更长(如 5 秒)在大多数情况下都可以工作,但这不是一个好的解决方案。 我不明白为什么sendReadyConfirmationaddEventListener 中。我大致了解您想要做什么(在发送数据之前等待窗口准备好),但在我看来,只需要sendReadyConfirmation,或者直接在ngOnInit 上的constructor。在发送“READY”消息之前监听消息有什么意义? 这只是试图确认通信正在发生...... Ritesh Waghela 提到使用 onload 和有点工作......我仍然有一些问题 window.parent in popup 不起作用.. 我想只适用于 iFrame。因此,在父级中,我向子级弹出窗口发送了“INIT”消息,并让子级确认消息已收到并“就绪”,然后再发送另一条消息。是的,这样做看起来没有意义。但简单地说,如果在弹出窗口中有与父窗口通信的方式,那就太好了。正如下面提到的 Ritesh Waghela,onload 事件将知道何时启动子弹出窗口然后发送消息。它工作得更好,但有时子弹出窗口仍然没有收到消息。带 onload 的 1 秒 setTimeout 将起作用 【参考方案1】:

您需要做的是在窗口加载成功时发送消息:

const printWindow = window.open("/print", "Print_Me", windowFeatures);
 printWindow.onload = () => 
   printWindow.postMessage(printPageStatus: "INIT", window.origin)
;

【讨论】:

@Zeo,成功了吗? 它工作得更好....但不是一直...我知道为什么有时该消息没有发生,会告诉你 它工作得更好,但有时孩子弹出仍然没有收到消息。 onload 内的 1 秒 setTimeout 将工作 100%

以上是关于window.postMessage 到 Angular 中的弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章

js--window.postMessage

跨域通信--Window.postMessage()

HTML5中window.postMessage,在两个页面之间的数据传递

使用 window.postMessage 发送敏感数据是不是安全?

Internet Explorer 11 中的 window.postMessage 是不是有最大长度限制?

window.postMessage解决跨域