Promise的含义

Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理且更强大。

Promise对象具有以下两个特点:

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有3中状态:Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。
  2. 一旦状态改变就不会再变,任何时候都可以得到这个结果。

Promise也有一些缺点:

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  2. 如果不设置回调函数,Promise内部抛出的错误不会反应奥外部。
  3. 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚开始还是即将完成)。

基本用法

ES6规定,Promise对象是一个构造函数,用来生成Promise实例。

var promise = new Promise(function(resolve,reject) {

    //  ...some code

    If( /*异步操作成功*/){

        resolve(value);

    }else{

        reject(error);

    }

});

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。这两个函数有JavaScript引擎提供,不需要自己部署。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”。reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”。

Promise.prototype.then()

Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。

promise.then(function(value){

    //成功

},function(error){

    //失败

});

then方法接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为成功时调用,是必填的。第二个是Promise对象的状态变为失败时调用,是选填的。

Promise.prototype.catch()

Promise.prototype.catch()方法是.then(null,rejection)的别名,用于发生失败时的回调函数。

如果异步操作抛出错误,状态就会变为Rejected,然后就会调用catch方法指定的回调函数处理这个错误。

promise.then( (val) => {......} )

.catch( error) => {......} );

//等价于:

promise.then( (val) => {......}, (error) => {......} )

另外,then方法指定的回调函数如果在运行中抛出错误,也会被catch方法捕获。

promise.then( (val) => {

    trow new error(“此错误也会被catch捕获到”);

 } ).catch(

    (error) => {......}

 );

catch方法返回的还是一个Promise对象,因此后面还可以接着条用then方法。

promise.then( (val) => {

    ......

 } ).catch(

(error) => {......}

 ).then(

    (value2) => { ...... }

);

如果后面的then方法里面报错,就与前面的catch无关了。

Promise.all()

Promise.all方法用于将多个Promise实例包装成一个新的Promise实例。

var p = Promise.all( [ p1, p2, p3] );

Promise.all方法接受一个数组作为参数(不一定是数组,但必须是具有Iterator接口,且返回的每个成员都是Promise实例),p1, p2, p3都是Promise对象的实例。

P的状态由p1、 p2、 p3决定,分为两种情况:

  1. 只有p1、 p2、 p3的状态都变成Fulfilled,p的状态才会变成Fulfilled,此时p1、 p2、 p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1、 p2、 p3中有一个被Rejected,p的装填就变成Rejected,此时第一个被Rejected的实例返回值会传递给p的回调函数。

如果作为参数的Promise实例自身定义了catch方法,那么它被rejected时并不会触发Promise.all()的catch方法。如下面的例子:

const p1 = new Promise((resolve,reject) => {

    resolve(‘hello’);

})

.then(result => result)

.catch(e => e);

const p2 = new Promise((resolve,reject) => {

    throw new error(“报错了”);

})

.then(result => result)

.catch(e => e);

Promise.all([p1, p2])

.then( result => console.log(result ) )

.catch(e => console.log(“e”));

//[ ‘hello’, Error:报错了]

如果去掉p2的catch方法则会执行Promise.all的catch方法。

const p1 = new Promise((resolve,reject) => {

    resolve(‘hello’);

})

.then(result => result);

const p2 = new Promise((resolve,reject) => {

throw new error(“报错了”);

})

.then(result => result)

.catch(e => e);

Promise.all([p1, p2])

.then( result => console.log(result ) )

.catch(e => console.log(“e”));

// Error:报错了

Promise.race()

Promise.all方法同样是将多个Promise实例包装成一个新的Promise实例。

var p = Promise.race( [ p1, p2, p3] );

与 Promise.all不同的是,只要p1、 p2、 p3中有一个率先改变状态,P的状态就跟着改变。

Promise.resolved()

将现有的对象转化为Promise对象。

Promise.resolve(‘foo’);

//等价于

new Promise(result => result(“foo”))

Promise.reject()

返回一个新的Promise实例,状态为Rejected。

var p = Promise.reject(“出错了”);

//等同于

var p = new Promise(( resolve, reject) => reject(“出错了”));

两个有用的附加方法

done()

无论Promise对象的回调链以then方法还是catch方法结束,只要最后一个方法抛出错误,都有可能无法捕捉到。因此done方法就派上了用场,它总处于回调链的尾端,保证任何可能抛出的错误都会被捕捉到。

asyncFunc()

.then()

.catch()

.then()

.done();

finally()

Finally方法用于指定不管Promise对象最后状态如何都会执行的操作。它与done方法的最大区别在于,它接受一个普通的回调函数作为参数,该函数不管则么样都必须执行。

asyncFunc()

.then()

.catch()

.finally();

应用

加载图片

const preloadImage = function (path) {

    return new Promise(

        (resolve, reject) => {

            var img = new Image();

            img.onload = () => resolve("成功");

            img.onerror = () => reject("失败");

            img.src = path;

        }

    ).then(

    value => {console.log(value)   //异步加载成功则调用该方法

    }).catch(

    value => console.log(value)   //异步加载失败则调用该方法

);

 

12-09 14:46