手写promise (ts)

314 阅读3分钟

主要实现功能:

  • resolve
  • reject
  • Promise.then
  • Promise.catch
  • Promise.all
  • Promise.reac

思路和上篇文章一致:

  1. 设定三个状态 PENDING、FULFILLED、REJECTED,只能由PENDING改变为FULFILLED、REJECTED,并且只能改变一次
  2. MyPromise接收一个函数executor,executor有两个参数resolve方法和reject方法
  3. resolve将PENDING改变为FULFILLED
  4. reject将PENDING改变为FULFILLED
  5. promise变为FULFILLED状态后具有一个唯一的value
  6. promise变为REJECTED状态后具有一个唯一的reason

先申明部分常用类型

interface Resolve {
    (value: unknown): void
}
interface Reject {
    (reason: unknown): void
}
interface Exector {
    (resolve: Resolve, reject: Reject): void
}
interface CallBackFn {
    (): void
}
interface FulfilledFn {
    (value: unknown): unknown
}
interface RejectedFn {
    (reason: unknown): unknown
}

class封装和js大同小异,不过加了一些类型定义,不同的是把state、value、reason等变量定义由构造函数内部移到了class,使用private声明为私有属性

class myPromiseForTS {
    //  1、设定3个状态值,只能由PENDING转变成FULFILLED或REJECTED,且只能转变一次。
    #PENDING: string = 'pending'
    #FULFILLED: string = 'fulfilled'
    #REJECTED: string = 'rejected'

    private state: string = this.#PENDING               // 状态存储
    private value: unknown = null                       // resolve方法返回的唯一值
    private reason: unknown = null                      // reject方法返回的唯一值  
    private onFulfilledCallBacks: CallBackFn[] = []     // fulfilled状态的回调数组
    private onRejectedCallBacks: CallBackFn[] = []      // rejected状态的回调数组

    // 2、创建构造函数,传入一个执行器函数
    constructor(exector?: Exector) {
        const resolve: Resolve = (value: unknown): void => {
            if (this.state === this.#PENDING) {
                this.state = this.#FULFILLED
                this.value = value
                this.onFulfilledCallBacks.forEach((fun: CallBackFn): void => {
                    fun()
                })
            }
        }
        const reject: Reject = (reason: unknown): void => {
            if (this.state === this.#PENDING) {
                this.state = this.#REJECTED
                this.reason = reason
                this.onRejectedCallBacks.forEach((fun: CallBackFn): void => {
                    fun()
                })
            }
        }
        // && 确保exector方法存在再执行,避免ts报错, 下面同理
        try {
            exector && exector(resolve, reject)
        } catch (err: unknown) {
            reject(err)
        }
    }

    // then方法
    // 通过settimeOut来模拟异步调用,保证链式调用,所以then方法抛出的是一个新的promis,并将返回值进行resolve
    then(onFulfilled: FulfilledFn | null, onRejected?: RejectedFn): myPromiseForTS {
        if (!onFulfilled || typeof onFulfilled !== 'function') {
            onFulfilled = (value: unknown): unknown => value
        }
        if (!onRejected || typeof onRejected !== 'function') {
            onRejected = (reason: unknown): unknown => reason
        }
        const myPromiseForTS_: myPromiseForTS = new myPromiseForTS((resolve: Resolve, reject: Reject) => {
            switch (this.state) {
                // PENDING状态时将回调方法全部存在到回调数组内
                case this.#PENDING:
                    this.onFulfilledCallBacks.push(() => {
                        setTimeout(() => {
                            try {
                                const result: unknown = onFulfilled && onFulfilled(this.value) 
                                resolve(result)
                            } catch (err: unknown) {
                                reject(err)
                            }
                        }, 0)
                    })
                    this.onRejectedCallBacks.push(() => {
                        setTimeout(() => {
                            try {
                                const result: unknown = onRejected && onRejected(this.reason)
                                resolve(result)
                            } catch (err: unknown) {
                                reject(err)
                            }
                        }, 0)
                    })
                    break
                case this.#FULFILLED:
                    setTimeout(() => {
                        try {
                            const result: unknown = onFulfilled && onFulfilled(this.value)
                            resolve(result)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                    break
                case this.#REJECTED:
                    setTimeout(() => {
                        try {
                            const result: unknown = onRejected && onRejected(this.reason)
                            reject(result)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                    break
            }
        })
        return myPromiseForTS_
    }

    // catch方法    
    catch(onRejected: RejectedFn): myPromiseForTS {
        return this.then(null, onRejected)
    }

    // finally方法
    finally(fn: Function): myPromiseForTS {
        return this.then((value) => {
            fn()
            return value
        }, (reason) => {
            fn()
            throw reason
        })
    }

    // all方法,接收一个promise数组,当所有promise状态都为resolve时执行resolve
    all(promises: myPromiseForTS[]): myPromiseForTS {
        return new myPromiseForTS((resolve, reject) => {
            if (promises.length === 0) {
                resolve([])
            } else {
                const result: unknown[] = [] // 接受promise返回值
                for (let i: number = 0; i < promises.length; i++) {
                    promises[i].then(data => {
                        result[i] = data
                        if (++i === promises.length) {
                            resolve(result)
                        }
                    }, (err: unknown) => {
                        reject(err)
                        return
                    })
                }
            }
        })
    }

    //reac方法,接收一个promise数组,当有一个promise状态为resolve时执行resolve
    reac(promises: myPromiseForTS[]): myPromiseForTS {
        return new myPromiseForTS((resolve, reject) => {
            if (promises.length === 0) {
                resolve(null)
            } else {
                for (let i: number = 0; i < promises.length; i++) {
                    promises[i].then(data => {
                        resolve(data)
                    }, reason => {
                        reject(reason)
                        return
                    })
                }
            }
        })
    }
}

下面老规矩,测试方法和测试结果截图

function testFn(type: String): myPromiseForTS {
    return new myPromiseForTS((resolve, reject) => {
        switch (type) {
            case 'resolve':
                resolve('resolve is success !')
                break
            case 'reject':
                reject('reject is success !')
                break
            case 'finallyResolve':
                resolve('finallyResolve is success !')
                break
            case 'finallyReject':
                reject('finallyReject is success !')
                break
        }
    })
}

const tsFn1: myPromiseForTS = testFn('resolve')
tsFn1.then(e => {
    console.log(e)
})
// 输出: resolve is success !


const tsFn2: myPromiseForTS = testFn('reject')
tsFn2.catch(e => {
    console.log(e)
})
// 输出: 'reject is success !

const tsFn3: myPromiseForTS = testFn('finallyResolve')
tsFn3.then(e => {
    console.log(e)
}).finally(() => {
    console.log('finally is success !')
})
// 输出: finallyResolve is success !
// 输出: finally is success !

const tsFn4: myPromiseForTS = testFn('finallyReject')
tsFn4.catch(e => {
    console.log(e)
}).finally(() => {
    console.log('finally is success !')
})
// 输出: finallyReject is success !
// 输出: finally is success !

new myPromiseForTS().all([tsFn1, tsFn3]).then(e => {
    console.log('promiseAll', e)
})
// 输出: promiseAll [ 'resolve is success !', 'finallyResolve is success !' ]

new myPromiseForTS().reac([tsFn1, tsFn2]).then(e => {
    console.log('promissReac', e)
})
// 输出: promissReac resolve is success !

1651470279.png

有写得不好的地方欢迎指出,万分感谢~~~~