这里有一个相对稳定的方法(演示),它使用了Deferred
s,在IE 6-9、Chrome 19、Firefox 3.6-10、Opera 10.10-11.52、Android 4和iOS 5中经过测试并且可行。
首先,我们将编写一个小型的jQuery插件,为jQuery集合中的每个元素返回一个Deferred
数组。每个Deferred
将在元素加载时解决;如果元素加载失败或(可选)超过timeout
秒,则会被拒绝。
$.fn.loaded = function(opts) {
var o = $.extend({timeout:10000}, opts)
, r = [];
this.each(function() {
var dfd = new $.Deferred(), el = $(this), to;
if (o.timeout) to = setTimeout(function() {
done();
dfd.reject();
}, o.timeout);
el.bind('load.dfdl', function() {
done();
dfd.resolve();
}).bind('error.dfdl', function() {
done();
dfd.reject();
});
function done() {
clearTimeout(to);
el.unbind('.dfdl');
}
r.push(dfd.promise());
});
return r;
};
超时机制将防止浏览器从未实际触发任何事件的情况。我在这里设置了默认超时时间为10秒;在现实世界中,您可能希望将其缩短。
现在我们将生成10个随机大小的placekittens,用作示例中的图像。
var imgs=[];
for (var i = 0; i < 10; i++) imgs.push('<img src="http://placekitten.com/' + rnd() + '/' + rnd() + '"> ');
$('#imgs').html(imgs.join());
最后,我们将用一些魔法将所有东西集成在一起:
$.when.apply($, $('#imgs img').loaded({timeout:10000}) ).done(function() {
alert('loaded successfully');
}).fail(function() {
alert('load failed or timed out');
});
$.when
创建一个主 Deferred
,只有当所有子 Deferred
解决时才会被解决,或者在子 Deferred
拒绝时拒绝。它通常希望您将每个 Deferred
作为参数传递(不支持传递 Deferred
数组),因此我们必须 apply
我们的数组。(我可能会做 $.whenall = function(dfds) { $.when.apply($,dfds); };
这样你的应用程序代码就有了更清晰的 $.whenall( $('#imgs img').loaded() )...
)