不要忘记跨域 iframe 的载入情况April 1, 2008

在编写某个 跨域的 Ajax 调用 功能时,出现了个匪夷所思的问题,就是无法载入 iframe 中的连接器(YAHOO.util.Connect),代码和操作无任何的问题。

在麻烦了 圆心 同志 N 遍以后,发现原来是 iframe 没有完全载入,框架中的代码没有运行的缘故。(在这里再次感谢下他,Orz)

这的确是个非常普遍的问题,由于网速的缘故,往往父页面载入完成,而 iframe 中的内容还正在读取。这个时候,父页面调用子页面中的对象时,就会发生问题。

我想到了个变通的办法,就是「等待」子页面载入完成以后,再去尝试运行。如果子页面还没有载入相应的对象,那么就「再等待」一段时间再去尝试。

可能表述上有所欠缺,我们还是看具体的代码。

为了理解,首先说明已经在 HTML 中已经包含了此 iframe,并子页面中也包含了 YUI 的框架代码及相应的控件。

<iframe src="http://.../proxy.htm" id="proxy"></iframe>

下面是相应的 Javascript 代码

var proxy = $('proxy').contentWindow;
Controler.disable = true;  // 获取数据此段期间,禁止用户输入
if (typeof proxy.YAHOO == 'undefined') {
    // 等待一段时间再去尝试,Function 为父类的名称
    setTimeout(function() {Function.get(URL)}, 100); 
    return;
}

// 已经得到子页面对象,获取数据
proxy.YAHOO.util.Connect.asyncRequest('GET', URL, {
    success: function(req) {
        alert(req.responseText);
        Controler.disable = false; // 恢复用户输入
    },

    failure: function() {
        return false;
    }
});

不过这个代码还有很多的问题,目前所能预见到的,就是客户端的资源占用问题。可想而知,如果反复的请求数据对于浏览器来说,资源花销将是非常大的。

大家如果有更好的办法,不妨说说。

§ 11 条评论

  1. 虽然没看明白你的问题到底在哪里?

    不过在iframe的window对象上使用使用onload事件处理函数不行吗?

  2. @Lunatic Sun 是这样的,由于 YUI 组建比较巨大,载入需要一段时间。往往父页面载入以后,子页面(iframe 页面)并没有完全执行完毕文档内的 Javascript,造成短期内父页面访问子页面的 YAHOO 基类失败。

    这个问题在《Javascript 高级程序设计》中有介绍(第 426 页) -- 有点咬文嚼字的味道了 :^)

  3. 是啊 所以我说在iframe的window对象上使用onload事件处理函数不行吗?

  4. @Lunatic Sun 不幸的是由于都是统一用这个文件,所以是只读的

  5. 你说的这个问题,和《Javascript 高级程序设计》中的这个问题,并非一个问题,书中使用setTimeout的理由在于DOM tree没有完全加载完成,关于这一技巧可以参看Realazy最近的<a href="http://realazy.org/blog/2008/03/29/understand-0-settimeout/">文章</a>。

    而你所说的这个问题不能够通过
    $('proxy').contentWindow.onload = function(){
    // this.YAHOO
    };
    解决吗?

  6. @Lunatic Sun 这个控件不是一次性调用的,下次也是需要用到它

  7. 上次提到过跨域 Ajax 的调用问题,这次做个总结。众所周知,Javascript 有“同源策略”的限制。但有时候偏偏又要碰到 Ajax 跨域调用的问题,这个时候就需要些“特殊”的方法使脚本正常使用。

    总结下目前所能想到的一些策略,具体的可以查看 Yahoo 开发中心的相关文档。

    iframe 方法
    具体详情,可以参看这里。

    实现的原理就是 iframe 与 父页面 进行 Javascript 通信。完全跨域操作没有测试过,但跨子域名是完全可行的。

    优势(部分)

    全部使用 Javas

  8. @Lunatic Sun
    我一直用的是 Grace 的方法,不用 onload 的原因是有时你不清楚你前边的人,或者后边的人是否也在用 onload 。

  9. 蚂蚁 蚂蚁

    判断iframe可以参考这段代码,
    iframe id jsProxy:
    if('IE') {
    document.getElementById("jsProxy").onreadystatechange = function () {
    if(this.readyState == "complete") {
    //sendToBatch();
    this.onreadystatechange = null;
    }
    }
    }else{
    document.getElementById("jsProxy").onload = function () {
    //sendToBatch();自定义函数
    }
    }

  10. tianxz tianxz

    iframe 和 parent page 能交互?

  11. Hi,

    thanks for the great quality of your blog, each time i come here, i'm amazed.

    black hattitude.

添加评论




* Required (but your email address will never be published)

Yahoo 统计