关于大量iframe加载的解决方案

手头的一个项目,根据客户的要求,在前端自动生成大量的iframe,比如90个iframe,而且这些iframe是嵌套在一个大的iframe下的,不要问我为什么这样。

方案1:将动态生成的url,附加到iframe的src中,比如后端生成了90个iframe,那么将这些数据返回到浏览器,然后让浏览器自动去请求。

这个时候的现象是:浏览器直接假死,就是任何操作都已经做不了了。

猜想原因是:当文档加载完成时,将会去自动发起90个iframe的请求,这个太消耗浏览器资源了,当时我依稀记得chrome可以同时发起4个连接,因此,我猜想可能是由于多个线程去争夺连接资源,导致效率太低,因此,必须限制连接数,因此,发起请求的操作必须要有js来控制。

方案2:将动态生成的url保存在页面的某个位置,然后生成的iframe的src为空(没有连接请求)。然后在大的iframe加载完毕之后,调用如下函数进行加载:

//onload
var count = $("#div iframe").size();//iframe的个数
updateIframeSrc(0,count);
updateIframeSrc(1,count);
updateIframeSrc(2,count);

function updateIframeSrc(index,count){
     if(index >= count)
         return;
     var iframe  = $("#rawdiv iframe").eq(index);
     iframe.load(function(){

        console.log(index+"complete");
        updateIframeSrc(index+3,count);
    });
    var url = "......";
    iframe.attr(src,url);
}

我的想法数如果能充分利用浏览器最大连接数为4的特性,使用其中3个去并发操作,然后这样就可以充分利用网络资源了,同时又不至于太卡顿。但是我没找到jquery发起并发的方法,于是只能自作聪明的写了一段类似于递归的方法,当上个文档加载完成时在去加载下一个。

结果:仍然是存在卡顿现象,而且其中有些iframe中的内容无法显示完整文档,但是这个链接时正确的,把两个html拿出来比对了一下,发现iframe中请求的document缺少了一部分,而且是中间缺少了一部分,这个是什么原因,我现在也不清楚,,,,

紧接着,我调研了一下js如何开启多线程。结果答案非常失望:js引擎只能是单线程的,浏览器核心有多个线程,包括但不仅限于连接线程(默认4个),gui渲染线程,js线程。由于js单线程的特性,导致实现起来比较简单,不需要考虑同步问题。与此同时,文章里面描述了js引擎对事件处理的机制。

js是种靠事件驱动的机制,有点像消费者和生产者一样。浏览器核心不停的像一个队列添加事件,比如浏览器点击事件,定时时间等等,而js处理是每次都去取队列头中的元素(如果有的话),然后调用响应函数,并且并且,当这个元素没处理完之前是不会处理下一个的。这也就解释了为什么会出现卡顿,因为鼠标的动作发到js引擎时,前面有太多事件要操作,导致鼠标事件无法处理。

方案3:加载iframe的时间间隔错开,说白了,给js引擎留出处理其他事件的时间。于是有了下面代码

for(var i = 0;i<count;i++){
    setTimeout(function(){
        var iframe = $("#rawdiv iframe").eq(i);
        iframe.attr("src",iframe.attr("id"));
    },i*1000);
}

意思时当文档加载完成时,添加一系列的定时事件。即定时更改iframe的src。

但是但是!!!do not work!!! 我调试了一下,在setTimeout函数内部获取到的i值总是最后一个值,原因不明。
既然如此,那使用setInterval会如何呢?即有了如下代码

var index = 0;
var timer = setInterval(function(){
if(index >= count){
  clearInterval(timer);
  return;
}
updateIframeSrc(index++)},500);

OK!可以正常work了。

方案4:于是我又尝试了一下最开始的做法,将代码变成如下,同样可以work!

//main

setTimeout(updateIframeSrc(0),500);
//可以添加一些限制,比如index == count时就返回。不过这里没有判断也可以,因为下次事件的加载是在本次加载完成之后才设置的。而setinterval 则一直向js引擎中添加事件,因此,必须及时取消。

function updateIframeSrc(index){
    var iframe = $("#rawdiv iframe").eq(index);
    iframe.attr("src",iframe.attr("id"));
    iframe.load(function(){
        setTimeout(function(){
            updateIframeSrc(++index);
        },500);
    });
}

这段代码就是当上个iframe加载完成之后,再设定一个新的定时去加载,间隔500毫秒,用于处理一些其他操作。

上面两种方法,个人更青睐于第二种,因为每个iframe加载时间不相同,将加载间隔设死,当上个iframe加载时间太长时,将会导致马上处理下个iframe的加载,会存在一点点卡顿。

参考链接:这里写链接内容

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值