您的位置:首页 > 其它

es6 promise的应用

2018-03-12 11:03 120 查看
Promise正如它的中文意思“承诺”一样,保存着未来会发生事件(一般为异步操作)。Promise避免了“回调地狱”,写法更加接近同步操作。说到同步,我更加喜欢async、await,它们书写更贴近同步操作。图片加载往往是异步的,如果有操作需要等到所有的图片加载完之后再执行,这时候就需要不断的监听所有图片的加载情况。ES5利用ES5实现多图预加载,可以通过计数器判断有多少图片加载完成。

var count = 0,    // 计数器
imgs = [];

/*
* (Array)source 图片url
* (Fun)cb 回调
*/
function preLoadImg(source, cb) {
source.forEach(function(url, i) {
imgs[i] = new Image();
imgs[i].onload = function() {
if(++count === source.length) {
cb && cb();
}
}
imgs.src = url;
})
}

ES6ES6原生提供了Promise对象,接下来用Promise改写上面的代码。
// 预处理图片
function preLoadImg(source){
let pr = [];
source.forEach(url => {// 预加载图片
let p = loadImage(url)
.then(img => this.images.push(img))
.catch(err => console.log(err))
pr.push(p);
})

// 图片全部加载完
Promise.all(pr)
.then(() => {
// do sth
});

}
// 预加载图片
function loadImage(url) {
return new Promise((resolve, reject) => {
let img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
})
}

Promise实际上是将回调操作独立出来,当Promise状态从pending(进行中)改为resolved(已完成),then注册的函数就会被执行,如果状态从pending改为rejected(已失败),就会被catch捕获。这里向Promise.all传入了一个数组(可以不是数组,具有iterator接口对象均可以,但返回的成员都必须是Promise实例,如果不是Promise实例,也会调用Promise.resolve转化为Promise实例),数组中的Promise状态均为resolved,Promise.all的状态才会是resolved,否则Promise.all的状态为rejected。也就是说,当所有图片加载完成后,才会执行then中的函数。但是,如果参数中的Promise实例自己有定义catch方法,那么当rejected的时候,就会被自己的catch捕获,catch方法执行完后,是会返回一个新的,状态为resolve的Promise实例,因此,传给Promise.all的是这个新的,状态为resolve的Promise。为了防止有图片加载失败,阻塞后续操作,为每一个p添加catch,捕获reject,Primise.all就接受不到了。下面是一个案例,目的是当页面的图片都加载完才把图片显示到页面中,如果其中有一个出错了就不显示。
1 function loading(src) {
2   return new Promise((resolve, reject) => {
3     let img = document.createElement("img");
4     img.src = src;
5     img.onload = function () {
6       resolve(img);
7     };
8     img.onerror = function (err) {
9       reject(err)
10     }
11   })
12 }
13
14 function showimg(imgs) {
15   imgs.forEach(function (img) {
16     document.body.appendChild(img);
17   });
18 }
19 Promise.all([
20   loading("./img/banner01.jpg"),
21   loading("./img/banner02.jpg")
22 ]).then(showimg);

 下面这个例子是当图片先加载的先显示出来,没加载的就不再显示了。
1 function loading(src) {
2   return new Promise((resolve, reject) => {
3     let img = document.createElement("img");
4     img.src = src;
5     img.onload = function () {
6       resolve(img);
7     };
8     img.onerror = function (err) {
9       reject(err)
10     }
11   })
12 }
13
14 function showimg(imgs) {
15   let p = document.createElement("p");
16   p.appendChild(imgs)
17   document.body.appendChild(p);
18 }
19 Promise.race([
20   loading("./img/banner01.jpg"),
21   loading("./img/banner02.jpg")
22 ]).then(showimg);

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: