Promise 含义Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。Promise 对象有以下两个特点:对象的状态不受外界影响。有三种状态,分别为 pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态改变,就不会再变,任何时候都可以得到这个结果。状态改变只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。使用 Promise 对象的好处在于:可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。Promise 对象提供统一的接口,使得控制异步操作更加容易。Promise 缺点:无法取消 Promise,一旦新建它就会立即执行,无法中途取消。如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。基本用法ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。const promise = new Promise((resolve, reject) => { setTimeout(() => { const num = Math.random(); if (num > 0.5) { resolve(num); } else { reject(num); } }, 500);});promise.then( res => { console.log(“成功:” + res); }, err => { console.log(“失败:” + err); });Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。resolve 函数的作用:将 Promise 对象的状态从“未完成(pending)”变为“成功(resolved)”,在异步操作成功时调用,并将异步操作的结果作为参数传递出去。reject 函数的作用:将 Promise 对象的状态从“未完成(pending)”变为“失败(rejected)”在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。then 方法作用:接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。第二个函数可选,不一定要提供,也可以将第二个函数作为 catch 方法的参数。catch 方法作用:用于指定发生错误时的回调函数。Promise 对象异步操作抛出错误,状态就会变为 rejected,就会调用 catch 方法指定的回调函数处理这个错误。另外,then 方法指定的回调函数,如果运行中抛出错误,也会被 catch 方法捕获。const promise = new Promise((resolve, reject) => { setTimeout(() => { const num = Math.random(); if (num > 0.5) { resolve(num); } else { reject(num); } }, 500);});promise .then(res => { console.log(“成功:” + res); }) .catch(err => { console.log(“失败:” + err); });promise .then(res => { console.log(“成功:” + res); throw new Error(“test”); }) .catch(err => { // num > 0.5时打印 “失败:Error: test” console.log(“失败:” + err); });Promise 执行顺序Promise 新建后立即执行,then 方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,catch 同理。调用 resolve 或 reject 并不会终结 Promise 的参数函数的执行。const promise = new Promise((resolve, reject) => { console.log(“我是第一个执行的”); resolve();});promise.then(res => { console.log(“我是第三个执行的”);});console.log(“我是第二个执行的”);resolve 函数和 reject 函数的参数reject 函数的参数通常是 Error 对象的实例,表示抛出的错误;resolve 函数的参数除了正常的值以外,还可能是另一个 Promise 实例。如果一个 Promise(P2) 的 resolve 参数是另一个 Promise(P1),此时 P1 的状态就会传给 P2,P1 的状态决定了 P2 的状态,P1 的状态改变,P2 的回调函数才会执行。const p1 = new Promise(function(resolve, reject) { setTimeout(() => reject(new Error(“fail”)), 3000);});const p2 = new Promise(function(resolve, reject) { setTimeout(() => resolve(p1), 1000);});p2.then(result => console.log(result)).catch(error => console.log(error));// Error: fail上面代码中,p1 是一个 Promise,3 秒之后变为 rejected。p2 的状态在 1 秒之后改变,resolve 方法返回的是 p1。由于 p2 返回的是另一个 Promise,导致 p2 自己的状态无效了,由 p1 的状态决定 p2 的状态。所以,后面的 then 语句都变成针对后者(p1)。又过了 2 秒,p1 变为 rejected,导致触发 catch 方法指定的回调函数。Promise 链式调用then 方法可以返回一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。const promise = new Promise((resolve, reject) => { resolve(“promise”);}) .then(res => { console.log(res); // promise return “promise1”; }) .then(res => { console.log(res); // promise1 return “promise2”; }) .then(res => { console.log(res); // promise2 });注意:只要一个 Promise 中抛出错误,将执行 catch 方法,then 链终止。const promise = new Promise((resolve, reject) => { resolve(“promise”);}) .then(res => { console.log(res); // promise throw new Error(“中止”); return “promise1”; }) .then(res => { console.log(res); return “promise2”; }) .then(res => { console.log(res); }) .catch(err => { console.log(err); // Error: 中止 });主动终止 then 链,通过 catch 方法来中止 promise chainconst promise = new Promise((resolve, reject) => { resolve(“promise”);}) .then(res => { console.log(res); // promise return Promise.reject({ notRealPromiseException: true }); }) .then(res => { console.log(res); return “promise2”; }) .then(res => { console.log(res); }) .catch(err => { if (err.notRealPromiseException) { return true; } console.log(err); });Promise.prototype.finally()finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。finally 本质上是 then 方法的特例,不接受任何参数,不依赖于 Promise 的执行结果promise.finally(() => { // 语句});// 等同于promise.then( result => { // 语句 return result; }, error => { // 语句 throw error; });Promise.all()Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。const promise = Promise.all([promise1, promise2, promise3])Promise.all 方法接受一个数组作为参数,promise、pro 米色、promise3 都是 Promise 实例,如果不是,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。(Promise.all 方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。了解 Iterator 接口)promise 的状态由 promise1、promise2、promise3 决定,分成两种情况。只有 promise1、promise2、promise3 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 promise1、promise2、promise3 的返回值组成一个数组,传递给 p 的回调函数。只要 promise1、promise2、promise3 之中有一个被 rejected,promise 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 promise 的回调函数。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: 报错了]上面代码中,p1 会 resolved,p2 首先会 rejected,但是 p2 有自己的 catch 方法,该方法返回的是一个新的 Promise 实例,p2 指向的实际上是这个实例。该实例执行完 catch 方法后,也会变成 resolved,导致 Promise.all()方法参数里面的两个实例都会 resolved,因此会调用 then 方法指定的回调函数,而不会调用 catch 方法指定的回调函数。如果 p2 没有自己的 catch 方法,就会调用 Promise.all()的 catch 方法。Promise.race()Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。const p = Promise.race([p1, p2, p3])只要 p1、p2、p3 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。Promise.race 方法的参数与 Promise.all 方法一样,如果不是 Promise 实例,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。Promise.resolve()将现有对象转化为 Promise 对象。const promise = Promise.resolve(‘Hello world’)参数是 Promise 实例,该方法不做任何改变。参数是一个 thenable 对象,先将对象转为 Promise 对象,然后立即执行 thenable 方法。相当于将 thenable 对象中的 then 方法处理的值作为参数传给 promise then 方法。let thenObj = { then(resolve, reject) { resolve(“Hello”); }};const promise = Promise.resolve(thenObj);promise.then(res => { console.log(res); // Hello});参数不是具有 then 方法的对象,或根本就不是对象,则 Promise.resolve 方法返回一个新的 Promise 对象,状态为 resolved。Promise.reject()Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为 rejected。