JS手寫Promise程式碼ES6方式實現

凍書發表於2020-12-03

本篇只簡單實現Promise,不包含鏈式呼叫等。若想詳細瞭解請參考連結,由於Promise實現採用了釋出訂閱模式,所以想要了解原理的可以參考觀察者模式和釋出訂閱模式的區別

程式碼實現

const STATUS = {
    PENDING: 'pending',
    FULFILLED: 'fulFilled',
    REJECTED: 'rejected'
}

class MyPromise {
    constructor(executor) {
        this.status = STATUS.PENDING    // 狀態值
        this.value = undefined          // 成功返回值
        this.reason = undefined         // 失敗返回值
        this.onFulFilledCallbacks = []  // 成功回撥執行佇列----up
        this.onRejectedCallbacks = []   // 失敗回撥執行佇列----up

        // 成功
        const resolve = (val) => {
            // PENDING用來遮蔽的,resolve和reject只能呼叫一個,不能同時呼叫
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.FULFILLED
                this.value = val
                this.onFulFilledCallbacks.forEach(fn => fn())   // ----up
            }
        }
        // 是失敗
        const reject = (reason) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.REJECTED
                this.reason = reason
                this.onRejectedCallbacks.forEach(fn => fn())   // ----up
            }
        }

        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }

    then(onFullFilled, onRejected) {
        // 同步呼叫判斷
        if (this.status === STATUS.FULFILLED) {
            onFullFilled(this.value)
        }
        if (this.status === STATUS.REJECTED) {
            onRejected(this.reason)
        }
        // 非同步呼叫判斷 ----up
        if (this.status === STATUS.PENDING) {
            this.onFulFilledCallbacks.push(() => {
                onFullFilled(this.value)
            })
            this.onRejectedCallbacks.push(() => {
                onRejected(this.reason)
            })
        }
    }
}

// const p = new MyPromise((resolve, reject) => {
//     // resolve('success')   // 走了成功就不會走失敗了
//     // throw new Error('失敗') // 失敗了就走resolve
//     // reject('failed')       // 走了失敗就不會走成功
//     resolve('成功!')
// })
// p.then((res) => {
//     console.log(res)
// }, (err) => {
//     console.log(err)
// })

const p = new MyPromise((resolve, reject) => {
    setTimeout(function() {
        resolve('success')
    }, 1000)
})
p.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})

相關文章