如何检查打开的跨域窗口是否准备好接收邮寄消息? [英] How do I check if the opened cross domain window is ready to receive postmessage?

查看:34
本文介绍了如何检查打开的跨域窗口是否准备好接收邮寄消息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I launch a URL from another domain and then postMessage to it

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

在我启动的子窗口中,JavaScript代码如下所示对其兴趣进行注册:

The JavaScript code, in the child window I launch, registers its interest as follows:

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

问题在于,有时子窗口中有太多代码要运行,才能注册兴趣,以致无法接收到已发布的消息.

The problem is that sometimes there's so much code to run in the child window before it's able to register interest that it doesn't receive the posted message.

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

How do I reliably know that the cross-domain child window is ready to receive messages? I tried to register child.onload, but that doesn't fire as it's cross-domain. Is there anything else like passing a parameter to window.open that can guarantee the delivery of the message?

其他可能相关的信息:

  • 我正在使用62版的Chrome.
  • 我最终使用跨域窗口的真正原因是因为我要确保在子窗口中获得新的渲染线程,因为要完成的渲染非常繁重.如果我使用相同的来源,Chrome似乎会重用渲染器进程,因此会重用同一线程.

推荐答案

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

I have found no way to do this directly. The difficulty is that can't listen to events on cross-domain windows, so there is no direct way to know when it's finished loading and ready to accept your posted message.

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

A quick work-around is to use a timeout:

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

当然,如果孩子的加载速度真的很慢,则不能保证以这种方式.

Of course this way is not guaranteed if the child is really slow in loading.

如果您有权访问子代码,则可以使用上面的"setInterval"并继续调用postMessage,直到子代码使用"event.source.postMessage()"返回消息为止,如

If you have access to the child code, then you use "setInterval" above and keep calling postMessage until the child returns back a message using "event.source.postMessage()" as explained in the MDN page for postMessage. The parent would also need to set up a message listener. Once the parent gets the message back, you clear the interval. I would also make a limit so interval stops running after a certain number of attempts.

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

If you can't access the child code, there is one other way, which involves using an iFrame. Once you have an iframe, you can know when it's finished loading (even if it's loading from a different domain). This is how I got it to work:

  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的实际工作,等待其完成,然后发布消息.

  1. In your parent page, open the child-container html, attach a load listener. When it loads you call the loadChildApp function, which will do the real work of loading the iframe, waiting for it to finish, then posting the message.

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

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

One minor downside of this technique is that the child's true title and url (in the address bar) will not be shown to the user. They will just see the title you gave and the url of the child-container.html

这篇关于如何检查打开的跨域窗口是否准备好接收邮寄消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆