封装Promise
本文仅根据 Promise A+ 规范实现,与v8引擎提供的Promsie行为略有不同。案例在文章结尾。
准备状态
- 准备promise状态
const enum Status {
pending = 'pending',
fulfilled = 'fulfilled',
rejected = 'rejected'
}
- promise 实例上要有 then,catch,finally 方法,promise支持连续
.
调用,所以这三个方法都要返回一个 promise
interface ThenAble {
then(resFunc: (arg: any) => any, rejFunc?: (arg: any) => any): _Promise
catch(res: (arg: any) => any): _Promise
finally(res: (arg: any) => any): _Promise
}
- promise要能够进行状态流转、数据更新,但状态流转、数据更新的方法在外部不允许访问
// 抽象类 定义内部状态
abstract class __Promise {
// 定义 status 保存状态
protected status: Status
// 定义 data 保存数据
protected data: unknown
// 定义状态流转方式
protected abstract toResolve(arg: any): any
protected abstract toReject(arg: any): any
// 初始化状态,数据
constructor() {
this.status = Status.pending
this.data = undefined
}
}
- 创建 _Promise 类继承 __Promise 并实现 ThenAble接口
class _Promise extends __Promise implements ThenAble{
// ... 省去其他部分代码
// 首先实现toResolve 方法
protected toResolve(arg: any) {
// 判断当前 Promise 状态,仅在 pending 状态下更新状态和数据
if (this.status !== Status.pending) {
return
}
this.status = Status.fulfilled
this.data = arg
}
// toreject方法 同上,仅在 pending 状态下更新状态和数据
protected toReject(arg: any) {
if (this.status !== Status.pending) {
return
}
this.status = Status.rejected
this.data = arg
}
// then 方法
then(resFunc: (arg: any) => any, rejFunc?: ((arg: any) => any)): _Promise {
// 保存当前 this 用于在比闭包中查看当前promise状态
const that = this
// 返回 promise 支持连续 . 调用
return new _Promise((res, rej) => {
// 创建 thenCallback 便于之后加入 微任务队列
const doCallback = () => {
// 根据 promise 状态执行不同的回调函数
if (that.status === Status.fulfilled) {
if (typeof resFunc === 'function') {
const data = resFunc(that.data)
// 仅当 resFunc 显示返回一个 promise 时 then 可以返回 rejected 状态的 promise
if (data instanceof _Promise) {
data.then((d) => {
res(d) }, d => {
rej(d) })
} else {
res(data)
}
}
return
}
// 根据 promise 状态执行不同的回调函数
if (that.status === Status.rejected) {
if (typeof rejFunc === 'function') {
const data = rejFunc(that.data)
// 当传入 rejFunc 时 仅在 rejFunc 显示返回一个 promise 时 then 可能返回一个 rejected 状态的 promise
if (data instanceof _Promise) {
data.then(d => res(d), d => rej(d))
} else {
res(data)
}
}
// 未传入 rejFunc 时,将当前 promise 状态、数据传递给 then 返回的 promise
else {
rej(that.data)
}
return
}
// promise 仍为 pending 状态 创建宏任务,将 thenCallback 再次加入到微任务队列
setTimeout(() => {
queueMicrotask(doCallback) })
}
queueMicrotask(doCallback)
})
}
// catch 方法 和 then 方法相同思路,但只在 promise 状态为 rejected 时执行回调
catch(catchFunc: (arg: any) => any): _Promise {
const that = this
return new _Promise(((res, rej) => {
const catchCallback = () => {
// 仅在当前状态为 pending 时将 catchCallback 再次加入到微任务队列
if (that.status === Status.pending) {
setTimeout(() =>