前面已经更新了很多关于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世界》电子版,也算是大家的一点小福利吧。
