在执行函数之前等待多个 iFrame 加载

Waiting for multiple iFrames to load before executing function

本文关键字:iFrame 加载 等待 执行 函数      更新时间:2023-09-26

原谅我的天真,这可能很明显,我现在看不到。

请告诉我以下代码有什么问题:

    $('#iframe1').load(function(){
      $('#iframe2').load(function(){
        alert('loaded!');
      });
    }); 

这个想法是等到两个 iframe 都完全加载,然后发出警报"加载" - 当然,为了堆栈,这是一个简化的示例。

脚本位于 html 文档正文末尾的脚本标记中。

@Quertiy答案完全没问题,但不是很jQuery-ish。它仅针对 2 个 iframe 进行硬编码。

jQuery的美妙之处在于,你可以让它为最多的人工作,尽可能少的摩擦。

我建议使用一个非常简单的插件,它几乎可以完成该答案中存在的内容,但以更开放的方式。它不仅适用于 iframe,还适用于图像、音频、视频以及任何具有onload事件的内容!

无需进一步说明,代码如下:

(function($){
    $.fn.extend({allLoaded: function(fn){
        if(!(fn instanceof Function))
        {
            throw new TypeError('fn must be a function');
        }
        var $elems = this;
        var waiting = this.length;
        var handler = function(){
            --waiting;
            if(!waiting)
            {
                setTimeout(fn.bind(window), 4);
            }
        };
        return $elems.one('load.allLoaded', handler);
    }});
})(window.jQuery);

它的工作原理是向该选择中的每个元素添加一个load处理程序。由于它是一个插件,因此您可以以您决定使用它的任何方式使用。

下面是一个加载 30 个随机图像的示例:

//plugin code
(function($){
	$.fn.extend({allLoaded: function(fn){
		if(!(fn instanceof Function))
		{
			throw new TypeError('fn must be a function');
		}
		
		var $elems = this;
		var waiting = this.length;
		
		var handler = function(){
			--waiting;
			if(!waiting)
			{
				setTimeout(fn.bind(window), 4);
			}
		};
		
		return $elems.one('load.allLoaded', handler);
	}});
})(window.jQuery);
$(function(){
	//generates the code for the 30 images
	for(var i = 0, html = ''; i < 30; i++)
		html += '<img data-src="http://lorempixel.com/g/400/200/?_=' + Math.random() + '">';
	
	//stuffs the code into the body
	$('#imgs').html(html);
	
	//we select all images now
	$('img')
		.allLoaded(function(){
			//runs when done
			alert('loaded all')
		})
		.each(function(){
			//the image URL is on a `data` attribute, to delay the loading
			this.src = this.getAttribute('data-src')
		})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id="imgs"></div>


正如之前多次说过的那样,您的问题是您的 iframe 附加了一个load事件。每次内容更改都会触发该事件。

之后,您将#iframe2 上设置一个新事件。当它的内容发生变化时,它会左右、上方和您想要的东西触发事件!

最好的方法是跟踪您加载了哪些。加载完所有内容后,您只需运行该函数即可。

问题是您要等到#iframe1加载后再附加处理程序以进行#iframe2加载。因此,如果#iframe2先加载,您将永远不会收到回调。

相反,请观看它们load事件,并跟踪您看到了哪些事件:

var seen1 = false,
    seen2 = false;
$('#iframe1, #iframe2').load(function(){
    if (this.id == "iframe1") {
        seen1 = true;
    } else {
        seen2 = true;
    }
    if (seen1 && seen2) {
        alert('loaded!');
    }
});

为什么你期望第二个 iframe 在第一个之后加载?

~function () {
  var loaded = 0;
  $('#iframe1, #iframe2').load(function (){
    if (++loaded === 2) {
      alert('loaded!');
    }
  });
}()