如何让JavaScript等待所有图片加载完成后再继续执行?
顺序加载图片并获取宽高的简单方案
为什么你的代码没生效?
第一个for循环的问题:图片加载是异步操作,
onload回调会在浏览器完成图片加载后才触发,但循环结束后的console.log是同步执行的——这时候图片还没加载好,所以宽高都是0。即使你用let i避免了循环变量的作用域问题,本质上还是没等待异步加载完成就执行了后续代码。while循环的问题:JavaScript是单线程的,
while(loaded < images.length)会一直占用主线程,浏览器根本没机会处理图片加载的onload回调,导致loaded永远不会递增,陷入无限循环,页面直接卡死。
两种简单可行的方案
方案1:递归加载(新手友好,逻辑直观)
通过递归函数,确保一张图片加载完成后再加载下一张:
const imageLinks = ['a.png', 'b.png']; const loadedImages = []; // 存储加载完成的图片 function loadNext(index) { // 所有图片加载完成,执行后续逻辑 if (index >= imageLinks.length) { console.log('所有图片加载完成:'); loadedImages.forEach(img => { console.log(`宽:${img.width},高:${img.height}`); }); return; } const img = new Image(); img.onload = () => { console.log(`第${index+1}张加载完成`); loadedImages.push(img); loadNext(index + 1); // 加载下一张 }; // 处理加载失败的情况(可选) img.onerror = () => { console.error(`第${index+1}张加载失败:${imageLinks[index]}`); loadNext(index + 1); // 失败也继续加载下一张,可根据需求调整 }; img.src = imageLinks[index]; } // 启动加载第一张 loadNext(0);
这个方法逻辑直白:每次只处理一张图片,等它加载完成(onload触发)后,再调用自己加载下一张,完全不会阻塞主线程。
方案2:用Promise + async/await(稍进阶,但代码更简洁)
把图片加载包装成Promise,再用async/await实现顺序加载,代码看起来像同步逻辑,但实际是异步的:
const imageLinks = ['a.png', 'b.png']; // 把单张图片加载包装成Promise function loadSingleImage(url) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => resolve(img); img.onerror = () => reject(`加载失败:${url}`); img.src = url; }); } // 顺序加载所有图片 async function loadAllImages() { for (const link of imageLinks) { try { const img = await loadSingleImage(link); console.log(`图片:${link},宽:${img.width},高:${img.height}`); // 这里可以把img存到数组里备用 } catch (err) { console.error(err); } } console.log('所有图片加载完成'); } // 启动加载 loadAllImages();
await会等待当前图片加载完成后,再执行循环的下一次迭代,完美实现顺序加载的需求,而且代码结构清晰。
注意点
- 两种方案都不需要依赖HTML中的图片元素,完全用JavaScript创建
Image对象实现加载。 - 记得处理
onerror情况,避免某一张图片加载失败导致整个流程卡住。
内容的提问来源于stack exchange,提问作者RobsonDaSheep
相关产品推荐
相关产品推荐

