实现一个Promise

本文根据Promise A+规范详细讲解如何封装一个Promise,重点介绍准备状态和Promise实例的方法如then、catch、finally。虽然与v8引擎的Promise行为有差异,但提供了完整的实现代码供参考。
摘要由CSDN通过智能技术生成
封装Promise

本文仅根据 Promise A+ 规范实现,与v8引擎提供的Promsie行为略有不同。案例在文章结尾。

准备状态
  1. 准备promise状态
const enum Status {
   
    pending = 'pending',
    fulfilled = 'fulfilled',
    rejected = 'rejected'
}
  1. 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
}
  1. 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
    }
}
  1. 创建 _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(() => 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值