拆分自定义Promise图片加载函数后无输出,存在浏览器表现差异
拆分代码后控制台无输出的原因及修复方案
核心原因
ES模块的执行时序问题:当使用
type="module"时,浏览器会延迟执行脚本(等同于defer属性的效果),直到整个HTML文档解析完成。此时你的图片可能已经通过缓存或快速加载完成,load事件早已触发,而你后续添加的事件监听器无法捕获这个已经发生过的事件,导致Promise永远处于pending状态,await一直等待,console.log自然不会执行。未处理图片已加载完成的状态:你的代码只监听了
load事件,但没有检查图片是否已经加载完成(通过img.complete属性),如果图片在脚本执行前就加载好了,Promise永远不会resolve。未处理加载错误:如果图片加载失败,你的代码没有监听
error事件,同样会导致Promise一直pending,无法走到console.log步骤。
另外,Chrome和Firefox的差异源于两者在模块脚本执行时机、图片缓存策略上的细微区别:Chrome可能更严格地让图片优先加载完成,导致即使合并成模块脚本也会错过load事件;而Firefox的时序处理可能让监听器有机会在图片加载完成前被添加。
修复方案
1. 修改utils.js中的Promise逻辑
添加img.complete检查,同时监听error事件避免Promise挂起:
const waitToLoadImgs = (imgEls) => { const imgElsPromise = imgEls.map((imgEl) => { return new Promise((resolve, reject) => { // 先检查图片是否已经加载完成 if (imgEl.complete) { return resolve("ok"); } // 定义事件处理函数,避免重复监听 const handleLoad = () => { cleanUpListeners(); resolve("ok"); }; const handleError = () => { cleanUpListeners(); reject(new Error(`图片加载失败: ${imgEl.src}`)); }; const cleanUpListeners = () => { imgEl.removeEventListener("load", handleLoad); imgEl.removeEventListener("error", handleError); }; imgEl.addEventListener("load", handleLoad); imgEl.addEventListener("error", handleError); }); }); return Promise.all(imgElsPromise); }; export { waitToLoadImgs };
2. 在scripts.js中添加错误捕获
async函数中的错误如果未被捕获会静默失败,所以添加try/catch块:
import { waitToLoadImgs } from "./utils.js"; const imgEls = [...document.querySelectorAll("img")]; const loadImgsResult = async () => { try { const result = await waitToLoadImgs(imgEls); console.log(result); } catch (err) { console.error("图片加载流程出错:", err); } }; loadImgsResult();
额外说明
如果测试时发现缓存影响结果,可以在图片URL后添加随机参数(比如?v=${Math.random()})来强制浏览器重新加载图片,验证修复效果。
内容的提问来源于stack exchange,提问作者JustANewCoder
相关产品推荐
相关产品推荐

