手写Promise

42 阅读1分钟


class MyPromise {
    static PENDING = 'pending'
    static FULFILLED = 'fulfilled'
    static REJECTED = 'rejected'

    state = MyPromise.PENDING

    result = null

    constructor(fun) {
        this.status = MyPromise.PENDING
        this.result = null

        try {
            fun(this.resolve, this.reject)
        } catch (error) {
            this.reject(error)
        }
    }

    resolve = (result) => {
        // 保证resolve是异步执行,在时间循环的末尾
        setTimeout(() => {
            if (this.status === MyPromise.PENDING) {
                this.status = MyPromise.FULFILLED
                this.result = result
                this.resolveCallBacks.forEach(callback => {
                    callback(result)
                })
            }
        })

    }
    
    reject = (result) => {
        // 保证reject是异步执行,在时间循环的末尾
        setTimeout(() => {
            if (this.status === MyPromise.PENDING) {
                this.status = MyPromise.REJECTED
                this.result = result
                this.rejectCallBacks.forEach(callback => {
                    callback(result)
                })
            }
        })

    }

    then = (onFULFILLED, onREJECTED) => {
        // 通过返回一个Promise来实现链式调用
        return new MyPromise((resolve, reject) => {
            // then可以接收不是函数的参数
            onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { }
            onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => { }
            // 避免异步执行时status状态未变更,导致回调不执行
            this.resolveCallBacks = []
            this.rejectCallBacks = []
            if (this.status === MyPromise.PENDING) {
                this.resolveCallBacks.push(onFULFILLED)
                this.rejectCallBacks.push(onREJECTED)
            }
            if (this.status === MyPromise.FULFILLED) {
                // 添加异步执行
                setTimeout(() => {
                    onFULFILLED(this.result)
                })
            }
            if (this.status === MyPromise.REJECTED) {
                setTimeout(() => {
                    onREJECTED(this.result)
                })
            }
        })
    }
}
console.log(1)
let m = new MyPromise((resolve, reject) => {
    console.log(2)
    setTimeout(() => {
        resolve('1s')
        reject('2s')
        console.log(4)
    })
})

m.then(
    (res) => { console.log(res) },
    (res) => { console.log(res.message) }
).then()
// console.log(m)

// export default MyPromise
console.log(3)