使用jQuery Deferred数组实现图片预加载失败,求问题排查
你的图片加载Deferred代码问题分析与修复
让我帮你拆解这段代码里的几个关键错误,正是它们导致了逻辑无法正常工作:
核心错误点
- Deferred对象引用混乱:你创建了
d = $.Deferred(),但却把未定义的p(应该是d)推进了promises数组,这直接导致$.when监听的是一堆无效对象,完全无法追踪图片加载状态。 - resolve方法未调用:
img.onload = function(){ p.resolve }这里只是引用了resolve方法,没有加括号执行,相当于什么都没做,Deferred永远不会进入resolved状态。 - 循环变量作用域泄漏:用
var i声明循环变量,会让所有异步的onload回调共享同一个i的引用。当onload触发时,循环早已结束,i的值等于length,srcs[i]会取到undefined,图片根本没加载正确。 - 未处理加载失败场景:如果某张图片加载失败(比如404),对应的Deferred会永远处于pending状态,
$.when会一直等待,永远不会触发done回调。
修复后的完整代码
var promises = []; var srcs = [/* 你的图片URL数组 */]; var length = srcs.length; for (let i = 0; i < length; i++) { // 每次循环创建独立的Deferred和Image对象 let deferred = $.Deferred(); promises.push(deferred); let img = new Image(); img.onload = function() { // 加载成功时标记Deferred为resolved,可传递当前img对象 deferred.resolve(this); }; img.onerror = function() { // 加载失败时标记为rejected,避免Deferred挂起 deferred.reject(this); }; // 设置图片src,触发加载 img.src = srcs[i]; } // 监听所有Deferred的状态 $.when.apply($, promises) .done(function() { defImages.resolve(); console.log("所有图片都加载完成啦!"); }) .fail(function(failedImg) { console.log("有图片加载失败:", failedImg.src); // 这里可以添加失败后的处理逻辑,比如重试或提示用户 });
关键修复说明
- 用
let声明变量:let会创建块级作用域,确保循环中每次迭代的i、deferred和img都是独立的,避免异步回调引用到错误的变量。 - 正确关联Deferred与图片:把每次创建的
deferred对象推进promises数组,让$.when能正确追踪每个图片的加载状态。 - 执行resolve/reject方法:在
onload和onerror中调用deferred.resolve()和deferred.reject(),确保Deferred状态能正确更新。 - 覆盖失败场景:添加
onerror处理,防止因单张图片加载失败导致整个流程挂起。
内容的提问来源于stack exchange,提问作者Kotanet
相关产品推荐
相关产品推荐

