JS图片预加载的三种实现方案详解
本文详细解析了JavaScript中实现图片预加载的三种主流方案。首先介绍基于原生Image对象与load事件监听的基础方法;其次讲解利用生成器函数结合Promise实现异步控制的进阶技巧;最后演示如何使用ES6的async/await语法将异步操作转化为同步风格,提升代码可读性。
图片预加载基本概念
预加载的核心概念在于:在用户访问页面时,提前将所需图片加载至本地缓存。当后续需要展示图片时,直接调用缓存资源进行渲染,从而避免等待加载的时间。这种技术广泛应用于图片密集的网页场景(如百度图库、淘宝、京东等电商平台),能显著提升用户的浏览体验。
单张图片预加载实现
针对单张图片的预加载实现,我们需要关注加载过程中的状态变化。
var img=new Image();
img.addEventListener("load",loadHandler);
img.src="./img/1.jpg";
document.body.appendChild(img);
console.log(img.width);
function loadHandler(e){
console.log(img.width);//当前图片的原始宽度
}
在代码执行过程中,如果在图片尚未加载完成时尝试获取其宽度,返回值为0。只有当图片完全加载完毕并插入DOM树完成渲染后,触发load事件的回调函数,此时才能正确获取到图片的原始宽度。
多张图片预加载方案
当需要预加载多张图片时,必须在本地建立缓存机制。下文将介绍三种用于预加载多张图片的具体实现方案。
方案一:load事件预加载
第一种方案:基于load事件的预加载。
假设需要加载100张图片,图片命名规则为1.jpg至100.jpg(后续示例沿用此命名规则)。
var num=1;
var list=[];
loadImage();
function loadImage(){
var img=new Image();
img.addEventListener("load",loadHandler);
img.src="./img/"+num+".jpg";
}
function loadHandler(e){
list.push(this.cloneNode());//复制当前图片元素
num++;
if(num>100){console.log(list);return;}
this.src="./img/"+num+".jpg"; //修改地址继续后触发load事件
}
上述代码的逻辑流程如下:
1. 创建一个Image对象实例。
2. 为该图片元素绑定load事件监听器。
3. 图片加载完成后,将当前加载好的图片克隆一份,并推入结果数组中。
4. 更新计数器num;若num的值超过100,则停止执行流程,并输出包含所有图片的数组。
5. 将当前图片的src属性修改为下一个图片的地址。由于src改变会重新触发load事件,因此会再次进入loadHandler函数,如此循环直至所有图片加载完成。
方案二:生成器函数预加载
第二种方案:利用生成器函数实现预加载。
function loadImage(src){
return new Promise(function(resolve,reject){
let img=new Image();
img.onload=function(){
resolve(img);//加载时执行resolve函数
}
img.onerror=function(){
reject(src+'这个地址错误');//抛出异常时执行reject函数
}
img.src=src;
})
}
function* fn(){
for(let i=1;i<100;i++){
yield loadImage("./img/"+i+".jpg");
}
}
let s=fn();
let value=s.next().value;
resume();
function resume(){
value.then(img=>{
console.log(img);//打印加载的图片标签
value=s.next().value;
if(value)resume();
});
}
上述代码的执行逻辑解析如下:
1. 调用生成器函数,并依次执行loadImage函数。
2. 在Promise对象内部创建图片元素。
3. 判断图片加载状态,若加载成功则执行Promise的resolve回调。
4. 执行resume函数,该函数内部处理Promise处于resolved状态时的逻辑。
5. 反复调用s.next().value,直到所有图片加载完毕。
方案三:Async/Await预加载
第三种方案:基于async/await的图片预加载。
function loadImage(src){
let p=new Promise(function(resolve,reject){
let img=new Image();
img.onload=function(){//加载时执行resolve函数
resolve(img);
}
img.onerror=function(){
reject(src);
}
img.src=src;
})
return p;
}
async function fn(){
let arr=[];
for(let i=3;i<80;i++){
await loadImage(`./img/${i}-.jpg`).then(img=>{
arr.push(img);
});
}
return arr;
}
fn().then(list=>{
console.log(list);//打印图片数组
})
该方法利用了ES6引入的async和await关键字,将异步操作转换为阻塞式的同步代码风格。
具体说明如下:
1. 使用async关键字声明的函数标识为异步函数。
2. 在async函数内部可以使用await关键字,其作用是使异步操作变为同步等待,即阻塞式等待。
3. 只有当await后的异步操作全部完成,代码才会继续向后执行。
4. async函数中的await关键字后必须跟随Promise对象。
5. 执行async函数后,其返回值是一个Promise对象。
以上介绍了三种图片预加载的实现方法,供开发者参考选用。
本文内容旨在帮助读者理解相关技术,希望对学习有所帮助,感谢支持。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
