我觉得实现 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 = PENDING
this.data = null
fn(this._resolve.bind(this))
}
_resolve(data) {
if (this.status === PENDING) {
this.status = FULFILLED
this.data = data
this.callback && this.callback(data)
}
}
then(fulfilledCallback) {
switch (this.status) {
case PENDING: // 针对情况1
this.callback = fulfilledCallback
break;
case FULFILLED: // 针对情况2
fulfilledCallback(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 = fulfilled
break;
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 = PENDING
this.data = null
fn(this._resolve.bind(this))
}
_resolve(data) {
if (this.status === PENDING) {
this.status = FULFILLED
this.data = data
this.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 = fulfilled
break;
case FULFILLED:
fulfilled()
break;
}
})
}
// 实现链式的核心的代码
resolvePromise(fulfillRes, resolve, reject) {
if(fulfillRes instanceof MyPromise) {
// 把 resolve 的 data 往下传
fulfillRes.then(resolve, reject)
} else {
resolve(fulfillRes)
}
}
}
推荐阅读
《从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节》: 详细讲了 Promise 的实现。