概述
这篇文章旨在解析 Promise的异步实现原理,并且以 ES6中的 Promise 为蓝本实现一个简单的 Promise。
通过自己动手实现一个 Promise 对象,可以熟悉很多可能不知道的 Promise 细节,同时也能对异步的理解更提升一步。
本文假设读者对 Promise 规范有一定理解,并且熟悉 ES6 中的 Promise 基本操作。
Promise 核心
Promise 概括来说是对异步的执行结果的描述对象。(这句话的理解很重要)
Promise 规范中规定了,promise 的状态只有3种:
- pending
- fulfilled
- rejected
顾名思义,对上面3个状态的解释就不再赘述,Promise 的状态一旦改变则不会再改变。
- Promise 规范中还规定了 Promise 中必须有 then 方法,这个方法也是实现异步的链式操作的基本。
具体的规范可以参见:https://promisesaplus.com
ES6 Promise细节
- Promise 构造器中必须传入函数,否则会抛出错误。(没有执行器还怎么做异步操作。。。)
- Promise.prototype上的 catch(onrejected) 方法是 then(null,onrejected) 的别名,并且会处理链之前的任何的reject。
- Promise.prototype 上的 then和 catch 方法总会返回一个全新的 Promise 对象。
- 如果传入构造器的函数中抛出了错误,该 promise 对象的[[PromiseStatus]]会赋值为 rejected,并且[[PromiseValue]]赋值为 Error 对象。
- then 中的回调如果抛出错误,返回的 promise 对象的[[PromiseStatus]]会赋值为 rejected,并且[[PromiseValue]]赋值为 Error 对象。
- then 中的回调返回值会影响 then 返回的 promise 对象。(下文会具体分析)
这部分内容参考: http://es6.ruanyifeng.com/#docs/promise
动手实现
做了上面的铺垫,实现一个 Promise 的思路就清晰很多了,本文使用 ES6 来进行实现,暂且把这个类取名为 GPromise吧(不覆盖原生的,便于和原生进行对比测试)。下文中 GPromise 代指将要实现的类,Promise 代指 ES6中的 Promise 类。
内部属性
在浏览器中打印出一个 Promise 实例会发现其中会包括两用”[[ ]]”包裹起来的属性,这是系统内部属性,只有JS 引擎能够访问。
[[PromiseStatus]]
[[PromiseValue]]
以上两个属性分别是 Promise 对象的状态和最终值。
我们自己不能实现内部属性,JS中私有属性特性(#修饰符现在还是提案)暂时也没有支持,所以暂且用”_”前缀规定私有属性,这样就模拟了Promise 中的两个内部属性。
class GPromise {
constructor(executor) {
this._promiseStatus = GPromise.PENDING;
this._promiseValue;
this.execute(executor);
}
execute(executor){
//...
}
then(onfulfilled, onrejected){
//...
}
}
GPromise.PENDING = 'pedding';
GPromise.FULFILLED = 'resolved';
GPromise.REJECTED = 'rejected';
执行器
- 传入构造器的executor为函数,并且在构造时就会执行。
- 我们给 executor 中传入 resolve 和 reject 参数,这两个参数都是函数,用于改变改变 _promiseStatus和 _promiseValue 的值。
- 并且内部做了捕获异常的操作,一旦传入的executor 函数执行抛出错误,GPromise 实例会变成 rejected状态,即 _promiseStatus赋值为’rejected’,并且 _promiseValue赋值为Error对象。
execute(executor) {
if (