ES6实现多张图片同时加载

前面已经更新了很多关于ES6的知识点,今天我们来综合的做一个小练习,让多张图片可以同时加载。

图片没有加载之前的状态是这样


HTML结构如下

<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>同时加载多张图片</title>
</head>
<body>
<div id='all'>
   <img src="./images/load.gif" alt="" id="a1">
   <img src="./images/load.gif" alt="" id="a2">
   <img src="./images/load.gif" alt="" id="a3">
   <img src="./images/load.gif" alt="" id="a4">
</div>
<script src='jQ.js'></script>
</body>
</html>

给出的data数据如下

{
"main": [{
"id": "a1",
"url": "http://localhost:8088/images/a.jpg"
},
{
"id": "a2",
"url": "http://localhost:8088/images/b.jpg"
},
{
"id": "a3",
"url": "http://localhost:8088/images/c.jpg"
},
{
"id": "a4",
"url": "http://localhost:8088/images/d.jpg"
}
]
}

DOM结构中已经给出了加载中的路径 img标签页已经存在了,我们需要做的是,在img的src属性加载完成之后把src属性替换一下就OK了。



首先,我们需要利用ajax把数据先请求过来,,还记得应该怎么写吗?

用jquery写ajax只需要传递一个对象就可以了,而且很多参数都可以省略,我就直接用默认的get方式请求了,请求路径是我自己在后台定义的路由,你们可以自己定义,当ajax请求成功的时候打印一下data数据的值,看一下是否可以打印到。



$.ajax({
url: '/data',
   success: (data) => {
var arr = JSON.parse(data).main;
       console.log(arr);
   }
});


请求到的数据没有错,接下来我们开始思考,这个同时加载的功能到底利用什么可以实现呢?



好像还想不起来,先不要着急,还记得如何判断一张图片是否加载完成吗?

先new一个image,然后给image一个src属性,image有一个onload的方法,是图片加载完成之后触发,当图片加载完成之后,把页面上的src属性覆盖掉就可以了。



for(let i =0 ;i<arr.length;i++){
let img = new Image();
   img.src = arr[i].url;
   img.onload = () => {
img.src = $('#all img').eq(i)[0].src;
   }
}

看上去上面的代码好像是完成了要求,所有的图片都加载出来了,可是是同步加载的,如何实现异步加载呢?



还记得前两天学习的小P么?可以实现异步加载的ES6新增对象Promise,我们来复习一下基本的语法

new Promise((reslove, reject) => {
if(){//如果条件满足,就调用reslove函数
       reslove();
   }
}).then(reslove=>{//成功状态下执行的代码
   })
   .catch(reject=>{报错或者失败状态下执行的代码
});

我们尝试一下利用Promise来改写上面的图片加载代码

先创建一个promise实例,代码的主体部分应该一样,先new一个image,然后给图片一个src属性

new Promise((reslove, reject) => {
let img = new Image();
   img.src = url;
}).then(reslove=>{}).catch(reject=>{});

小p里面有个特别重要的判断条件,决定了小p以后的人生,可是这个判断条件该如何写呢?满足什么情况下才会成功呢?



当图片加载完成之后,就是这个条件,可这个条件该如何写呢?当图片加载完成之后改变小p的状态不就好了,代码如下:

new Promise((reslove, reject) => {
let img = new Image();
   img.src = url;
   img.οnlοad=()=>{
reslove();
   }
}).then(reslove=>{}).catch(reject=>{});

当图片加载完成之后,调用小p成功状态下的回调函数,回调函数里面该写什么呢?

当图片加载完成之后,肯定是要替换页面中的路径,把图片呈现在用户的面前了,所以回调函数里面的代码应该是

$('#all img').eq(1).src=url;

url是我们需要用的参数,通过调用的时候把参数传递过来

new Promise((reslove, reject) => {
let img = new Image();
   img.src = url;
   img.οnlοad=()=>{
reslove(url);
   }
}).then(url=>{
$('#all img').eq(1)[0].src=url;
}).catch(reject=>{});

eq后面的参数我们不能写成死的,可是写很多遍又太麻烦,所以我们现在需要一个循环,把url地址和I下标传给小p

for(let i=0;i<arr.length;i++){
new Promise((reslove, reject) => {
let img = new Image();
       img.src = arr[i].url;
       img.οnlοad=()=>{
reslove(arr[i].url);
       }
}).then(url=>{
$('#all img').eq(i)[0].src=url;
   }).catch(reject=>{});
}

这次的代码看上去没什么问题了,我们来运行一下试试:


图片都加载出来了,这样就算结束了吗?

再仔细想想,有没有更好的办法,我们之前学过的一个方法,可以控制一个集合的promise实例。


Promise.all();

周六只是简单的跟大家提了一下,今天来介绍一下这个方法的主要功能,当他的状态变为成功的时候,会触发reslove的回调函数,回调函数里面的参数就是所有集合里面的小小p的成功函数参数的集合,也是一个数组,理解起来有一点点抽象对不对?我们画一张图来看看


上面的图片有一点点抽象,大家原谅一下我们这个灵魂画手。

我们换成代码表示就是

var arr=[1,2,3,4];
var pAll=[];
for (let i=0;i<arr.length;i++){
let p= new Promise((reslove,reject)=>{
reslove(arr[i]);
   });
   pAll.push(p);
};
Promise.all(pAll).then(reslove=>{
console.log(reslove);
console.log(arr);
});

arr数组里面每一项的值分别是每个小promise的参数,Promise.all成功函数的返回值刚好就是arr里面的每一项,符合了上面的一一对应。



我们尝试用这个方法来改写一下上面的代码,

那么这次就需要先let一个空数组,把每一个图片的promise先放在里面了;

let all=[];

我们先来封装一个函数来创建promise实例

    function addPromise(url) {
return new Promise((reslove, reject) => {
let img = new Image();
       img.src = url;
       img.onload = () => {
reslove(url);
       }
})
};

之后利用刚刚所学的Promise.all来进行改写上面的代码

for (let i = 0; i < arr.length; i++) {
arr.push(addPromise(arr[i].url));
};
Promise.all(arr).then(reslove => {
for (let i = 0; i < reslove.length; i++) {
$('#all img').eq(i)[0].src = reslove[i];
}

到这里为止,我们今天的任务就完成了,看一下整体的代码

$.ajax({
url: '/data',
   success: (data) => {
var arr = JSON.parse(data).main;

   function addPromise(url) {
return new Promise((reslove, reject) => {
let img = new Image();
       img.src = url;
       img.onload = () => {
reslove(url);
       }
})
};
   for (let i = 0; i < arr.length; i++) {
arr.push(addPromise(arr[i].url));
};
Promise.all(arr).then(reslove => {
for (let i = 0; i < reslove.length; i++) {
$('#all img').eq(i)[0].src = reslove[i];
}
});
}
});

先利用ajax进行参数的请求,之后用函数封装一个构造Promise的方法,promise里面判断图片是否加载完成,最后循环调用函数,利用Promise.all方法整体操作替换src路径。

今天算是又重新整理一遍了,希望我写的明白一点了,点击原文链接即可获得《css世界》电子版,也算是大家的一点小福利吧。

发布了16 篇原创文章 · 获赞 34 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/cmy0816/article/details/80362343
今日推荐