JavaScript - Try & Catch - 捕获 Window.postMessage() 错误的困难

18

我在使用window.postMessage()时遇到了捕获错误的困难。

我想要能够捕获我正在遇到的错误 -

"无法将消息发布到http://www.that-domain.com。接收方源为http://www.this-domain.com

简单的示例代码(应该会报错):

 try {
    window.postMessage('1','http://www.differentDomain.com');
 } 
 catch (e) {       
     alert('error');
 }

更详细的流程如下: 我使用jQuery将一个跨域iframe添加到文档中,然后将信息提交到它。这不应该出错,因为目标源应该匹配——它们都由proxyDomain变量设置。

var $iframeProxy = $('<iframe id="myIFrame" src="' + proxyDomain + '"></iframe>').appendTo('body');

window.storageProxy = $iframeProxy[0].contentWindow;

try {
    window.storageProxy.postMessage(message, proxyDomain);
}
catch (e) {       
    alert('error');
}

3
你是否解决了这个问题? - andy mccullough
1
很遗憾,我还没有。 - Kevin M
没有问题,谢谢你的回复。 - andy mccullough
3个回答

8

无法捕获错误,但通常情况下,如果目标源不同,则会发生错误,这种情况是测试和生产场景之间的区别。

因此,您可以检查父域是什么,并相应地更改目标源:

function getTargetOrigin()
{
    try {
        var url = (window.location != window.parent.location) ? document.referrer : document.location.href;
        if (url.indexOf('www.myproduction-website.com')!=-1)
            return document.location.protocol + '//www.myproduction-website.com'
        else //set the alternative target
            return document.location.protocol + '//' + url.split('/')[2];
    }
    catch(e) //falback to production
    {
        return document.location.protocol + '//www.myproduction-website.com'
    }
}

并在 postMessage 函数内使用它:

function postMessage(message){
    window.top.postMessage( message,getTargetOrigin());
}

使用此解决方案,您可以在多个服务器配置中使用相同的代码,而无需硬编码目标源URL。
如果您在框架内导航并重新检查document.referrer,则此解决方案将失败,在这种情况下,它将包含先前框架URL而不是父级URL。在这种情况下,请考虑将'*'用作targetOrigin URL,这是向其他域发送消息的唯一有效解决方案。
希望对您有所帮助!

2
仅为支持此答案,来自MDN的内容:“与任何异步调度的脚本(超时,用户生成的事件)一样,调用postMessage的调用者无法检测到侦听由postMessage发送的事件的事件处理程序抛出异常。” https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch - HotN
不再在try/catch文章中了。相反,未来的读者可以在MDN的postMessage文章中找到它。https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage - Dusty48

4

12
是的,但你如何让它变得安静并抓住它呢? - Lincoln B
1
URL已更改:https://html.spec.whatwg.org/multipage/web-messaging.html#posting-messages,现在是9.4.3第一注。 - sschoof

2

我会在 matteo-conta 的解决方案基础上增加更好的安全性,以防止假域名(例如www.myproduction-website.com.fakedomain.com)接收到消息:

function getTargetOrigin() {
    const domainDev = 'mydev-website.com';
    const domainProd = 'myproduction-website.com';
    try {
        var url = (window.location !== window.parent.location) ? document.referrer : document.location.href;
        const domain = url.split('/')[2];
        if (domain.endsWith(domainDev) || domain.endsWith(domainProd))
            return document.location.protocol + domain;
        else return '';
    } catch(e) {
        return ''
    }
}
const targetOrigin = getTargetOrigin();
try{
    if (targetOrigin) window.parent.postMessage(${msg}, targetOrigin);
} catch(e) {
    window.parent.postMessage(e, '*')
}

我还添加了将错误消息发布到任何目标来源的功能,这样您就可以使用以下方法在您网站的端口捕获它:
window.addEventListener("message", onResponse, false);
onResponse(res) {
    const data = _.get(res, 'data');
    if (res.origin === 'iframe-url-goes-here') {
        console.log('message from iframe', data)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接