目前我正在使用$( window ).load(function()
在所有图片加载后触发我的操作。
但有时当外部脚本或其他东西需要很长时间才能加载时,即使图像已经加载,我的函数也会很晚才会启动。
所以我想找到像$( document ).ready(function()
这样的函数,它等待所有加载的图像,然后运行我的函数。
我不需要整个文档准备就绪,我只需要为我的功能加载图像。
有这样的东西吗?
答案 0 :(得分:4)
是的,这实际上相当容易。图片元素上有一个complete
标记,当它们完成时会触发load
或error
个事件。所以我们可以这样做(参见下面有关表观复杂性的说明):
function getAllImagesDonePromise() {
// A jQuery-style promise we'll resolve
var d = $.Deferred();
// Get all images to start with (even complete ones)
var imgs = $("img");
// Add a one-time event handler for the load and error events on them
imgs.one("load.allimages error.allimages", function() {
// This one completed, remove it
imgs = imgs.not(this);
if (imgs.length == 0) {
// It was the last, resolve
d.resolve();
}
});
// Find the completed ones
var complete = imgs.filter(function() { return this.complete; });
// Remove our handler from completed ones, remove them from our list
complete.off(".allimages");
imgs = imgs.not(complete);
complete = undefined; // Don't need it anymore
// If none left, resolve; otherwise wait for events
if (imgs.length == 0) {
d.resolve();
}
// Return the promise for our deferred
return d.promise();
}
每当你需要检查时,就像这样使用它:
getAllImagesDonePromise().then(function() {
// They're all done
});
你可以在你放在正文末尾的脚本中使用它,就在结束</body>
标记之前(如果你愿意,可以在ready
回调中)。
你可能想知道“完整”图像的复杂性。为什么我们将事件挂钩,然后删除它们并取消事件?这是为了应对竞争条件。虽然浏览器在单个UI线程上运行主JavaScript,但浏览器 不是单线程。它可以随时完成加载图像并设置其complete
属性。如果发生这种情况,我们尚未与该图片上的load
/ error
事件挂钩,我们将不会收到通知。因此,如果我们首先过滤掉已完成的图像,然后将事件挂钩到剩余的图像上,那些在这些代码行之间完成的图像(再次:我们的代码是单线程的,浏览器不是)永远不要开火。所以我们挂钩事件,然后过滤掉已完成的事件,然后处理我们收到的任何事件。