JavaScript循环获取图片高度异常:部分sizes数组元素值为0
解决JavaScript中通过for循环创建Image实例时偶尔无法获取图片高度的问题
问题描述
我通过for循环创建了40个Image实例,每个实例随机选择三个指定图片路径中的一个,然后尝试获取图片高度存入sizes数组,路径存入tests数组。大部分时候正常,但偶尔sizes里会有元素是0,无法正确获取高度。我的代码如下:
let tests = []; let sizes = []; let deger; for (let index = 0; index < 40; index += 1) { let img = new Image(); let random = Math.floor(Math.random() * 3); if(random==0){ deger = '/img/test-1.png'; img.src = deger; sizes[index]=img.height; tests[index] = deger; }else if(random==1){ deger = '/img/test-2.png'; img.src = deger; sizes[index]=img.height; tests[index] = deger; }else{ deger = '/img/test-3.png'; img.src = deger; sizes[index]=img.height; tests[index] = deger; } } console.log(sizes);
问题根源
出现这个问题的核心原因是图片加载是异步操作:当你设置img.src后,浏览器才开始向服务器请求图片资源,这时候图片还没加载完成,img.height返回的是图片元素的初始默认值0,而非图片的实际高度。
偶尔能正常获取高度是因为浏览器可能缓存了这些图片,加载速度极快,刚好在你读取img.height时完成加载,但缓存状态不可控,所以会出现偶尔失败的情况。
解决方案
我们需要等待图片完全加载完成后再获取高度,这里提供两种实用方案:
方案1:使用onload事件监听加载完成
修改代码,在图片的onload回调中获取高度并存入数组,同时处理加载失败的场景:
let tests = []; let sizes = []; let completedCount = 0; const totalImages = 40; for (let index = 0; index < totalImages; index += 1) { let img = new Image(); let random = Math.floor(Math.random() * 3); let deger; // 用switch简化路径判断 switch(random) { case 0: deger = '/img/test-1.png'; break; case 1: deger = '/img/test-2.png'; break; default: deger = '/img/test-3.png'; } img.src = deger; tests[index] = deger; // 图片加载完成后再获取高度 img.onload = function() { sizes[index] = img.height; completedCount++; // 所有图片加载完成后再输出结果 if (completedCount === totalImages) { console.log(sizes); // 这里可以执行依赖图片尺寸的后续逻辑 } }; // 处理图片加载失败的情况 img.onerror = function() { sizes[index] = '加载失败'; completedCount++; if (completedCount === totalImages) { console.log(sizes); } }; }
方案2:使用Promise和Promise.all(更优雅的异步批量处理)
如果你的环境支持ES6+,可以用Promise封装图片加载逻辑,通过Promise.all等待所有图片加载完成后统一处理:
// 封装图片加载为Promise函数 function loadImage(src) { return new Promise((resolve, reject) => { const img = new Image(); img.src = src; img.onload = () => resolve({ src, height: img.height }); img.onerror = () => reject(new Error(`加载图片失败: ${src}`)); }); } const totalImages = 40; const imagePromises = []; for (let index = 0; index < totalImages; index += 1) { let random = Math.floor(Math.random() * 3); let deger; switch(random) { case 0: deger = '/img/test-1.png'; break; case 1: deger = '/img/test-2.png'; break; default: deger = '/img/test-3.png'; } imagePromises.push(loadImage(deger)); } // 等待所有图片加载完成 Promise.all(imagePromises) .then(results => { const tests = results.map(item => item.src); const sizes = results.map(item => item.height); console.log('tests数组:', tests); console.log('sizes数组:', sizes); // 执行后续业务逻辑 }) .catch(error => { console.error('图片加载出错:', error); });
关键提醒
- 永远不要在设置
img.src后立刻读取height/width,必须等待图片加载完成。 - 务必处理
onerror事件,避免因图片加载失败导致后续逻辑卡住。 - 使用Promise可以让异步代码更清晰,尤其适合批量处理多个异步操作的场景。
内容的提问来源于stack exchange,提问作者Reşit Abdullah Yavuzkol
相关产品推荐
相关产品推荐

