我如何检查打开的跨域窗口是否准备好接收邮寄消息?

问题描述 投票:1回答:1

我从另一个域启动URL,然后向其发布消息

const child = window.open("http://urlfromanotherdomain.com");
child.postMessage("you cant handle the message", "*");

我启动的子窗口中的JavaScript代码按如下所示注册其兴趣:

window.onmessage = function(ev) {window.console.log(ev);}

问题是,有时子窗口中有太多代码要运行,然后才能注册兴趣,因此它没有收到已发布的消息。

我如何可靠地知道跨域子窗口已准备好接收消息?我尝试注册child.onload,但是由于跨域,所以不会触发。还有其他什么可以将参数传递给window.open来保证消息传递的吗?

可能相关的其他信息:

  • 我正在使用Chrome的62版本。
  • 我最终使用跨域窗口的真正原因是,由于要进行的渲染非常繁琐,因此我想确保在子窗口中获得新的渲染线程。如果我使用相同的来源,Chrome似乎会重用渲染器进程,因此会使用相同的线程。
javascript google-chrome cross-domain
1个回答
0
投票

我发现无法直接执行此操作。困难在于无法在跨域窗口上侦听事件,因此无法直接知道何时加载完成并准备接受您发布的消息。

一种快速的解决方法是使用超时:

 var child = window.open( url, winId );
 setTimeout( function(){
     child.postMessage(data, url);
 }, 1000);

当然,如果孩子的加载速度真的很慢,则无法保证这种方式。

[如果您有权访问子代码,则使用上面的“ setInterval”并继续调用postMessage,直到该子项使用“ event.source.postMessage()”返回消息为止,如MDN page for postMessage中所述。父级还需要设置一个消息侦听器。父级收到消息后,请清除间隔。我也会做一个限制,以便间隔一定次数后停止运行。

如果无法访问子代码,则还有另一种方法,涉及使用iFrame。拥有iframe后,就可以知道它何时完成加载(即使它是从其他域加载的)。这就是我的工作方式:

  1. [用这样的js,css,html创建一个新的html页面,并将其命名为“ child-container.html”:

window.loadChildApp = function(url, json, title){
            window.document.title = title;
            var iframe = document.querySelector('#myIframe');
            iframe.src = url;
            document.querySelector('#loadingDiv').style.display = 'none';
            iframe.addEventListener('load', function(){
                iframe.contentWindow.postMessage(JSON.stringify(json), url);
            });
        }
#myIframe{
        height: 100%;
        width: 100%;
        border: none;
        margin: none;
    }
    
     #loadingDiv{
        height: 100%;
        width: 100%;
        margin: auto;
        padding: none;
    }
<div id="loadingDiv">Loading ... </div>
<iframe id="myIframe"  >
  1. 在您的父页面中,打开子容器html,附加一个加载侦听器。加载时,您调用loadChildApp函数,该函数将完成加载iframe的实际工作,等待其完成,然后发布消息。

        let win = window.open( 'child-container.html', key );
        win.addEventListener('load', function () {
            win.loadChildApp(url, data, title);
        });
    

此技术的一个小缺点是不会向用户显示孩子的真实标题和网址(在地址栏中)。他们将只看到您给的标题和child-container.html的网址。

© www.soinside.com 2019 - 2024. All rights reserved.