1 Promise 是什么
Promise 可以被理解为对象(或值)的代理,被代理的对象在被创建时状态是未知的,当被代理对象执行完成时,可以通过设置 Promise 的状态来触发相应的回调函数。
Promise 有下面三种状态:
- pending:初始状态,既不是成功,也不是失败
- fulfiled:操作成功
- rejected:操作失败
下面例子中,通过 Promise 的构造函数参数来配置异步操作,通过 then 的回调来配置成功、失败回调函数。当异步操作完成后,根据其执行结果,通过调用 resolve 或 reject 来设置 Promise 的对应状态,进而触发相应的回调函数。
1 | new Promise( function(resolve, reject) { |
2 Promise 的作用
Promise 可以将异步操作和其回调函数按照同步的方式进行书写,从而解决多层异步调用产生的回调地狱问题。
3 Promise 使用方法
下面所有方法的返回值都是新的 Promise 对象。
3.1 创建 Promise
1 | new Promise(function(resolve, reject){...} /*executor*/) |
参数
executor
executor 回调有两个参数 resolve 和 reject ,这两个参数是函数类型。创建 Promise 时 executor会被立即执行。当 resolve 或 reject 函数被调用时,表示需要将 Promise 对象的状态设置为 fullfilled 或 rejected,并触发对应状态的回调函数的执行。
1 | const myFirstPromise = new Promise((resolve, reject) => { |
3.2 类方法
Promise.all(iterable)
参数:interable 是多个 Promsie 对象的集合
作用:用于并行运行多个 Promsie 对象。
特点:
一旦有一个子 Promsie 参数失败,会触发父 Promsie 对象的失败状态,并将失败信息传递给父 Promsie 的失败回调函数。
当所有子 Promsie 参数都成功时,会触发父 Promsie 对象的成功状态,并将所有子 Promsie 参数的返回值按照顺序,以数组的形式传递给父 promise 的成功回调函数。
Promise.allSettled(iterable)
参数:interable 是多个 Promsie 对象的集合
作用:用于并行运行多个 Promsie 对象。
特点:
当所有子 Promsie 参数都完成(无论成功还是失败)时,会触发父 Promsie 对象完成状态,并将所有子 Promsie 参数的返回值按照顺序,以数组的形式返回。
1 | const promise1 = Promise.resolve(3); |
Promise.race(iterable)
参数:interable 是多个 Promsie 对象的集合
作用:用于并行运行 多个 Promsie 对象。
特点:
父 Promsie 的状态会和最快产生状态的子 Promsie 保持一致,并将最快子 Promsie 的返回值作为父 Promsie 相应状态回调的参数。
Promise.reject(reason)
作用:创建一个状态为失败的 Promise 对象,并将 reason 参数传递给对应的处理方法
Promise.resolve(value)
作用:创建一个状态由给定 value 决定的 Promise 对象。
特点:
如果 value 是 thenable (即,带有then方法的对象),返回的 Promise 对象的最终状态由then方法执行决定;否则的话(value 为空、基本类型或者不带 then 方法的对象),返回的 Promise 对象状态为 fulfilled,并且将该value 传递给对应的 then 方法。
通常而言,如果你不知道一个值是否是 Promise 对象,使用 Promise.resolve(value) 来返回一个 Promise 对象,这样就能将 value 作为 Promise 对象来使用。
3.3 实例方法
示例:
1 | var promise = new Promise( function(resolve, reject) { |
Promise.prototype.then(onFulfilled, onRejected)
给 Promise 对象添加 fulfiled 和 rejected 状态的回调。
Promise.prototype.catch(onRejected)
给 Promise 对象添加 rejected 状态的回调。
Promise.prototype.finally(onFinally)
给 Promise 对象添加一个一定会执行的回调。无论当前 Promise 的状态是完成(fulfilled)还是失败(rejected)
4 注意
4.1 回调执行时序
1、Promise 被创建时,配置给 Promise 构造函数的回调会被立即执行。
2、当多次添加 then 回调时,这些回调会按照被插入顺序独立执行。 配置给 Promise.then 的回调会被放入微队列,本轮事件循环运行完成之前这些回调都不会被执行。
4.2 链式调用
Promise 的链式调用,可以解决按顺序执行多个异步调用的诉求。
1 | const promise = doSomething(); |
promise2 代表 doSomething 、successCallback/failureCallback 已完成。
任何 promise2 新增的回调,都会在doSomething 、successCallback/failureCallback 之后执行。如果 successCallback/failureCallback 返回了新的 Promise 对象,则 promise2 会在 新 Promise 对象之后执行。
每一个 promise 的返回值,都是下一个promsie 回调函数的参数。
1 | new Promise(function(resolve, reject) { |
4.3 组合
Promise.all() 和 Promise.race() 是并行运行异步操作的两个组合式工具。
1 | Promise.all([func1(), func2(), func3()]) |
也可以使用 JavaScript 写法实现时序组合:
1 | func1 = function(lastValue) { |
4.4 嵌套
最好不好嵌套 Promise,容易出错。
1 | doSomethingCritical() |
这个内部的 catch 语句仅能捕获到 doSomethingOptional() 和 doSomethingExtraNice() 的失败,之后会继续moreCriticalStuff() 的运行。
4.5 异常
当有异常时,Promise 会中断,然后执行离的最近的 catch 或 rejectCallBack 回调来处理异常,当异常处理完成后,如果后面还有 then,则继续执行后面的 then 回调。
4.6 Promise 拒绝事件
当 Promise 触发 rejected 状态时,会有下面事件之一被派发到全局作用域(通常而言,就是window;如果是在 web worker 中使用的话,就是 Worker 或者其他 worker-based 接口):
rejectionhandled
当 Promise 被拒绝、并且在 reject 函数处理该 rejection 之后会派发此事件
unhandledrejection
当 Promise 被拒绝,但没有提供 reject 函数来处理该 rejection 时,会派发此事件。
1 | window.addEventListener("unhandledrejection", event => { |