13

1.Promise的含义

  • Promise是异步编程的一种解决方案

  • Promise实例代表一个异步操作,从它可以获取异步操作的消息

  • Promise实例有三种状态:

    • Pending:进行中

    • Resolved:已完成

    • Rejected:已失败

  • Promise实例的状态只能由 Pending->ResolvedPending->Rejected。一旦Promise实例的状态发生改变,就不会再发生变化,任何时候都可以得到这个结果

  • 为什么要使用Promise:通过Promise,可以将一步操作以同步操作的流程表达出来,可以避免层层嵌套的回调函数(回调地域),并且Promise提供了统一的接口,使得控制异步操作更加容易

2.Promise构造函数

Promise是一个构造函数,用来生成Promise实例

var promise = new Promise(function(resolve, reject)){
    // ... do something
    if (/*异步操作成果*/) {
        resolve(value)
    } else { /*异步操作失败*/
        reject(error)
    }
}
  • Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

  • resolve函数的作用是,将Promise实例的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去

  • reject函数的作用是,将Promise实例的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去**

Promise.prototype.then()

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

var promise = new Promise(function(resolve, reject)){
    // ... do something
    if (/*异步操作成果*/) {
        resolve(value)
    } else { /*异步操作失败*/
        reject(error)
    }
}
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
  • then方法可以接受两个回调函数作为参数。第一个回调函数是Promise的状态变为Resolved时调用,第二个回调函数是Promise实例的状态变为Rejected时调用。其中,第二个函数是可选的,不一定要提供。

  • 这两个函数都接受Promise实例传出的值作为参数。(简单地说就是:上面的promise对象在处理异步操作的过程中,如果调用了resolve方法,则会将resolve的参数传递给then方法的第一个函数,如果调用了reject方法,这会将reject的参数传递给then方法的第二个函数)

clipboard.png

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例),因此可以采用链式写法,即then方法后面在调用另一个then方法

clipboard.png

上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。(实际上是第一个then方法返回了一个Promise实例,在该实例中调用了resolve方法,而json.post则是作为resolve的参数)


clipboard.png

上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise实例,则第一个then方法会直接将该Promise实例返回

Promise.prototype.catch()

该方法是.then(undefined, onRejected)的别名,用于指定发生错误时的回调函数。

promise.then(function(data) {
    console.log('success');
}).catch(function(error) {
    console.log('error', error);
});

promise对象的错误,会一直向后传递,直到被捕获。即错误总会被下一个catch所捕获。then方法指定的回调函数,若抛出错误,也会被下一个catch捕获。catch中也能抛错,则需要后面的catch来捕获。

sendRequest('test.html').then(function(data1) {
    //do something
}).then(function (data2) {
    //do something
}).catch(function (error) {
    //处理前面三个Promise产生的错误
});

Promise.all()

该方法用于将多个Promise实例,包装成一个新的Promise实例

// p1,p2,p3都是promise实例
var p = Promise.all([p1, p2, p3]);

新的Promise实例的状态由三个promise实例共同决定

  • 当三个promise实例的状态都变为fulfilled,p的状态才会变为fulfilled,并将三个promise返回的结果,按照参数顺序存入数组,传给p的回调函数

  • 当p1, p2, p3其中之一状态变为rejected,p的状态也会变为rejected,并把第一个被reject的promise的返回值,传给p的回调函数

Promise..race()

该方法用于将多个Promise实例,包装成一个新的Promise实例

// p1,p2,p3都是promise实例
var p = Promise.race([p1, p2, p3]);

新的Promise实例的状态由三个promise实例共同决定

  • 当p1, p2, p3其中之一状态发生改变(变为fulfilled或者rejected),p的状态也会随之改变,并把第一个改变状态的promise的返回值,传给p的回调函数

Promise.resolve()

Promise.resolve方法的参数分为四种情况

  • 参数是一个Promise实例

如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

  • 参数是一个thenable对象

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。

  • 参数不是具有then方法的对象,或根本就不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。

Promise.resolve('Success');

/*******等同于*******/
new Promise(function (resolve) {
    resolve('Success');
});
  • 不带任何参数

直接返回一个Resolved状态的Promise对象。

Promise.resolve('Success');

/*******等同于*******/
new Promise(function (resolve) {
    resolve();
});

Promise.reject()

Promise.reject(new Error('error'));

/*******等同于*******/
new Promise(function (resolve, reject) {
    reject(new Error('error'));
});

这段代码会让这个Promise对象立即进入rejected状态,并将错误对象传递给then指定的onRejected回调函数。

参考资料

ECMAScript 6 入门


jhhfft
590 声望40 粉丝

Write the Code. Change the World.