我觉得实现 Promise,最难的部分是链式调用。下面是 Promise 链式调用的例子:
(new Promise(resolve => {resolve(1)})).then(data => {console.log(data)return new Promise(resolve => setTimeout(() => resolve(2), 100))}).then(data => {console.log(data)return Promise.resolve(3)}).then(data => console.log(data))
上面代码会依次输出: 1,2,3。链式调用就是一个个按顺序执行异步操作,把上一个 Promise 中 then 中的返回的数据,传递到到下一个 Promise 中。往下看前,大家可以试试看自己实现下 Promise 链式调用。
实现
1 支持非链式调用
我们先来实现个非链式调用的 MyPromise,满足下面的调用:
// 情况1: 输出 1。(new MyPromise(resolve => {resolve(1)})).then(data => console.log(data));// 情况2: 输出 2。(new MyPromise(resolve => {setTimeout(() => resolve(2), 100)})).then(data => console.log(data))
实现代码如下:
const PENDING = 'PENDING'const FULFILLED = 'FULFILLED'class MyPromise {constructor(fn) {this.status = PENDINGthis.data = nullfn(this._resolve.bind(this))}_resolve(data) {if (this.status === PENDING) {this.status = FULFILLEDthis.data = datathis.callback && this.callback(data)}}then(fulfilledCallback) {switch (this.status) {case PENDING: // 针对情况1this.callback = fulfilledCallbackbreak;case FULFILLED: // 针对情况2fulfilledCallback(this.data)break;}}}
2 支持链式调用
满足下面的调用:
// 依次输出:1,2,3(new MyPromise(resolve => {resolve(1)})).then((data) => {console.log(data)return new MyPromise(resolve => setTimeout(() => resolve(2), 100))}).then((data) => {console.log(data)return new MyPromise(resolve => setTimeout(() => resolve(3), 100))}).then((data) => {console.log(data)})
要支持链式调用,then 中返回的也应该是个 MyPromise 对象。并且返回的 MyPromise 对象要接上回调里的另一个 MyPromise 对象。只需改写 then 函数。代码实现如下:
then(fulfilledCallback) {return new MyPromise((resolve, reject) => {const fulfilled = () => {const res = fulfilledCallback(this.data)return this.resolvePromise(res, resolve, reject)}switch (this.status) {case PENDING:this.callback = fulfilledbreak;case FULFILLED:fulfilled()break;}})}resolvePromise(fulfillRes, resolve, reject) {if(fulfillRes instanceof MyPromise) {// 把 resolve 的 data 往下传fulfillRes.then(resolve, reject)} else {resolve(this.data)}}
以上,就实现了 Promise 的链式调用。完整代码如下:
const PENDING = 'PENDING'const FULFILLED = 'FULFILLED'class MyPromise {constructor(fn) {this.status = PENDINGthis.data = nullfn(this._resolve.bind(this))}_resolve(data) {if (this.status === PENDING) {this.status = FULFILLEDthis.data = datathis.callback && this.callback(data)}}then(fulfilledCallback) {return new MyPromise((resolve, reject) => {const fulfilled = () => {const res = fulfilledCallback(this.data)return this.resolvePromise(res, resolve, reject)}switch (this.status) {case PENDING:this.callback = fulfilledbreak;case FULFILLED:fulfilled()break;}})}// 实现链式的核心的代码resolvePromise(fulfillRes, resolve, reject) {if(fulfillRes instanceof MyPromise) {// 把 resolve 的 data 往下传fulfillRes.then(resolve, reject)} else {resolve(fulfillRes)}}}
推荐阅读
《从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节》: 详细讲了 Promise 的实现。
