手寫Promise源碼

const MyPromise = (() => {
    // 定義三種狀態
    const PENDING = 'pending';
    const RESOLVED = 'resolved';
    const REJECTED = 'rejected';


    // 不讓外界訪問的狀態數據
    const PromiseStatus = Symbol('PromiseStatus'); // 當前狀態
    const PromiseValue = Symbol('PromiseValue'); // 當前數據

    const changeStatus = Symbol('changeStatus'); // 封裝推向的狀態函數

    // 定義任務隊列
    const thenables = Symbol('thenables');
    const catchables = Symbol('catchables');

    // 定義後續處理函數
    const settleHandle = Symbol('settleHandle');

    // 創建串聯Promise
    const linkPromise = Symbol("linkPromise");


    // 定義構造器
    return class MyPromise {
        // newStatus 新的狀態  newValue // 新的數據 queue // 任務隊列
        [changeStatus](newStaus, newValue, queue) {
            // 只能是單向
            if (this[PromiseStatus] !== PENDING) {
                return
            }
            this[PromiseStatus] = newStaus;
            this[PromiseValue] = newValue;
            queue.forEach(hander => hander(newValue))
        }

        constructor(executor) {
            this[PromiseStatus] = PENDING; // 初始狀態是爲pending
            this[PromiseValue] = undefined; // 初始數據爲undefined

            // 定義任務隊列的數組
            this[thenables] = []; // resolveed
            this[catchables] = []; // rejected

            // 定義成功和失敗的推向函數 
            const resolve = data => {
                this[changeStatus](RESOLVED, data, this[thenables])
            }

            const reject = reason => {
                this[changeStatus](REJECTED, reason, this[catchables])
            }


            // 可以使用new Error 推向 reject
            try {
                executor(resolve, reject)
            } catch (error) {
                reject(error)
            }
        }

        // 定義then方法
        then(thenable, catchable) {
            return this[linkPromise](thenable, catchable)
        }

        // 定義catch方法
        catch (catchable) {
            return this[linkPromise](undefined, catchable)
        }

        // hander 後續處理函數
        // immediateStatus 立即執行的狀態
        // queue 作業隊列
        [settleHandle](handler, immediateStatus, queue) {
            if (typeof handler !== "function") {
                return
            }

            if (this[PromiseStatus] === immediateStatus) {
                setTimeout(() => {
                    handler(this[PromiseValue])
                }, 0)

            } else {
                queue.push(handler)
            }
        }

        // 定義串聯函數
        [linkPromise](thenable, catchable) {
            function exec(data, handler, resolve, reject) {
                try {
                    //得到promise的處理結果
                    const result = handler(data);
                    if (result instanceof MyPromise) {
                        result.then(d => {
                            resolve(d)
                        }, err => {
                            reject(err)
                        })
                    } else {
                        resolve(result)
                    }
                } catch (err) {
                    reject(err);
                }
            }

            return new MyPromise((resolve, reject) => {
                this[settleHandle](data => {
                    exec(data, thenable, resolve, reject)
                }, RESOLVED, this[thenables])

                this[settleHandle](reason => {
                    exec(reason, catchable, resolve, reject)
                }, REJECTED, this[catchables])
            })
        }

        static all(proms) {
            return new Promise((resolve, reject) => {
                const results = proms.map(p => {
                    const obj = {
                        result: undefined,
                        isResolved: false
                    }
                    p.then(data => {
                        obj.result = data;
                        obj.isResolved = true;
                        const unResolved = results.filter(r => !r.isResolved);
                        if (unResolved.length === 0) {
                            // 全部完成
                            resolve(results.map(r => r.result))
                        }
                    }, reson => {
                        reject(reson)
                    })
                    return obj;
                })
            })
        }
        static race(data) {
            return new Promise((resolve, reject) => {
                proms.forEach(p => {
                    p.then(data => {
                        resolve(data);
                    }, err => {
                        reject(err);
                    })
                })
            })
        }
        static resolve(data) {
            if (data instanceof MyPromise) {
                return data
            } else {
                return new MyPromise(resolve => {
                    resolve(data);
                })
            }

        }
        static reject(reason) {
            return newMyPromise((resolve, reject) => {
                reject(reason)
            })
        }



    }
})()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章