什么是 Promise
ES6 原生提供了 Promise 构造函数,用以解决异步编程中的回调地狱问题。该构造函数返回一个 Promise 实例,可以看作一个容器,保存着未来结束的某个事件的结果。
Promise 有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)。
每个 Promise 都会经历一个短暂的生命周期,操作成功 pending 变成 fulfilled,操作失败 pending 变成 rejected。只要这两种情况发生,状态就不会再变了。
基本用法
通过 new 操作符就可以实例化一个 Promise 对象,构造函数接收一个函数作为参数,这个过程是同步的,函数里面的代码会立即执行。
let p = new Promise(function (resolve, reject) { console.log(1);});console.log(2);// => 1// => 2复制代码
该函数的两个参数 resolve 和 reject,分别可以将 Promise 的状态从 pending 变成 fulfilled 和 rejected。
let p = new Promise(function (resolve, reject) { if (/*异步操作成功*/) { resolve(data); // pending 变成 fulfilled } else { reject(error); // pending 变成 rejected }});复制代码
then()
Promise 的原型对象具有 then 方法(Promise.prototype.then),供 Promise 实例调用。then 方法的第一个参数是 resolve 状态的回调函数,如果不需要,可以传 null。第二个参数是 reject 状态的回调函数,可以省略。
let p = new Promise(function (resolve, reject) { setTimeout(() => { resolve('Hello!'); }, 2000);});p.then(data => { console.log(data);}, error => { console.log(error);});// 等待两秒...// => 'Hello!'复制代码
then 方法支持链式操作,它的返回值是一个新的 Promise。如果一个 then 的回调函数的返回值是 Promise,那么下一个 then 会在该 Promise 状态改变后再被调用。
let p = new Promise(function (resolve, reject) { setTimeout(() => { resolve('Hello!'); }, 2000);});p.then(data => { console.log(data); return new Promise(function (resolve, reject) { setTimeout(() => { resolve('World!'); }, 2000); });}).then(data => { console.log(data);});// 等待两秒...// => 'Hello!'// 等待两秒...// => 'World!'复制代码
catch()
catch 同样是 Promise 原型对象的方法(Promise.prototype.catch),用于指定发生错误时的回调函数,该回调函数等同于 then 的第二个参数。
let p = new Promise(function (resolve, reject) { setTimeout(() => { resolve('Hello!'); }, 2000);});p.then(data => { throw new Error('第一个错误');}).then(data => { throw new Error('第二个错误');}).catch(error => { console.log(error);});// 等待两秒...// => Error: 第一个错误复制代码
all()
all 是 Promise 的静态方法(Promise.all)。它能够将多个 Promise 实例包装成一个新的 Promise 实例。新实例的状态由原来多个实例的状态决定,原实例都变成 fulfilled,新实例才会变成 fulfilled。只要有一个原实例变成 rejected,新实例也会变成 rejected。
race()
和 all 方法一样,race 也是 Promise 的静态方法(Promise.race)。它同样能将多个 Promise 实例包装成一个新的 Promise 实例。不同的是,只要原实例有一个改变了状态,新实例就立刻改变状态,第一个做出改变的原实例的返回值传递给新实例的回调函数。