es6-promise

书籍参考:《ECMAScript 6入门》 作者:阮一峰

文档参考:MDN

1.概念

Promise最初在社区提出的一个异步解决的方案,最后ES6将它加入了正式的标准,并规定了统一的写法。

在使用Promise之前,你需要注意下面几个点:

1.Promise有三个状态:Pending(进行中)Resolved(已完成)Rejected(已失败),这三个状态我们无法去改变,并且在一个Promise中只有两个可能,一种是从PendingResolved,另一种是PendingRejected。当结果发生后,这个状态就凝固了,也就是说我们无法去改变Promise对象的任何状态,如果再次调用这个Promise对象,返回的将是凝固状态的结果。

2.Promise在执行的过程中无法取消,并且我们也无法知道它执行到哪一步,我们只能知道返回的是已完成还是已失败。

3.Promise实例创建后会立即执行

下面的代码部署了一个Promise对象异步加载图片的例子,可以看到用Promise对象来编写异步代码是非常的清晰。

 var imgs = new Promise((resolve, reject) => {

    let img = new Image();

    img.src = 'http://xxx.com/img.jpg';

    img.onload = function(){
        resolve('加载成功');
    }

    img.onerror = function(){
        reject('加载失败');
    }
 });

在部署了Promise对象后,我们可以通过Promise的实例来调用then()方法,then()方法接受两个函数,这两个函数分别指定resolvedrejected状态返回的回调函数。第二个函数可以不指定,也就是说不返回错误,只得到完成的结果。

var imgs = new Promise((resolve, reject) => {

    let img = new Image();

    img.src = 'http://xxx.com/img.jpg';

    img.onload = function(){
        resolve('加载成功');
    }

    img.onerror = function(){
        reject('加载失败');
    }
});

imgs.then(function(value){
    console.log(value);
}, function(error){
    console.log(error);
});

Promise可以用于多个异步操作,下面的代码是判断img是否加载成功,如果加载成功就将img添加进div容器中。

var imgs = new Promise((resolve, reject) => {

    let img = new Image();

    img.src = 'http://xxx.com/img.jpg';

    img.onload = function(){
        resolve({
            img,
            status: '加载成功'
        });
    }

    img.onerror = function(){
        reject('加载失败');
    }
});

var loadImg = new Promise((resolve, reject) => {
    let imgDiv = document.getElementById('imgdiv');

    imgs.then(function(value){
        imgDiv.innerHtml(value.img);
    }, function(error){
        console.log(error);
    });
});


2.then()、catch()

Promise对象原型上定义了两个方法,分别为then()catch()then()和上面的一样,接受两个函数,可以不需要第二个函数,而catch()函数相当于then(null, reject)的别名。我们把上面的代码来修改,下面的代码同样能到达相同的效果,但是看上去更加简洁。

var imgs = new Promise((resolve, reject) => {

    let img = new Image();

    img.src = 'http://xxx.com/img.jpg';

    img.onload = function(){
        resolve('加载成功');
    }

    img.onerror = function(){
        reject('加载失败');
    }
});

imgs.then(function(value){
    console.log(value);
});

imgs.catch(function(error){
    console.log(error);
});

3.链式写法

由于Promise对象返回的是执行过后的一个新Promise对象,而then方法主要是捕获返回的对象里面PromiseStatus属性的值为’resolved’,而catch方法主要是捕获返回的对象里面PromiseStatus属性的值为’rejected’,而每次then或者catch都会返回一个新的Promise对象,这个新的Promise对象里的值就是从上一个Promise对象中获取的。从这些说明中,我们可以使用链式写法简洁明了的写出异步编程。

var imgs = new Promise((resolve, reject) => {

    let img = new Image();

    img.src = 'http://xxx.com/img.jpg';

    img.onload = function(){
        resolve('加载成功');
    }

    img.onerror = function(){
        reject('加载失败');
    }
});

imgs
    .then(value => console.log(value))
    .catch(error => console.log(error));

4.Promise.resolve()、Promise.rejcet()

Promise.resolve()方法接受一个参数,用于将参数转换为一个Promise对象。如果参数是一个基本类型值,那么将直接返回状态为resolved和值为参数的Promise对象

Promise.resolve($.ajax('http://www.youdao.com/'));

Promise.resolve(2); 

Promise.rejcet()方法和Promise.resolve()的用法一致,但返回的是一个已失败的Promise对象。

5.Promise.all()

Promise对象上有一个all方法,用于将一个数组或者具备Iterator接口的数据结构组合成一个多Promise对象实例的Promise对象。如果状态都是已完成,就会返回resolved状态,如果其中有一个Promise实例返回rejected。如果数组中的成员不是Promise对象,那么就调用Promise.resolve()方法返回一个有效的Promise对象。Promise.all()方法非常适合多个Promise对象控制,也就是说我需要10个异步调用都执行成功,那么可以用这个方法来控制。

比如下面,我需要两个图片都加载成功了才进行下一步操作。

var imgs1 = new Promise((resolve, reject) => {
    /* Code */
});

var imgs2 = new Promise((resolve, reject) => {
    /* Code */
});

Promise.all([imgs1, imgs2])
    .then(value => console.log(value))
    .catch(error => console.log(error));

6.Promise.race()

Promise.race()方法的使用和Promise.all()一致,但是行为不一致,Promise.race()方法接受的多个Promise对象中,只要有一个Promise对象的状态率先改变,那么Promise.race()的状态就为率先改变的Promise对象返回的状态。

文完

文档信息

发表评论

电子邮件地址不会被公开。 必填项已用*标注