成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

promise 實現(xiàn)(es6 完整源碼)

solocoder / 1817人閱讀

摘要:當(dāng)?shù)臓顟B(tài)已經(jīng)流轉(zhuǎn)時,回調(diào)函數(shù)會立即被執(zhí)行,當(dāng)還處于狀態(tài)時,回調(diào)函數(shù)被推入相應(yīng)隊列中等待執(zhí)行。

概覽
const PENDING = Symbol("PENDING");
const FULFILLED = Symbol("FULFILLED");
const REJECTED = Symbol("REJECTED");

class MyPromise {
    constructor(fn) {}
    then(successFn, failFn) {}
    catch(failFn) {}
    finally(finalFn){}
    static resolve(val) {}
    static reject(val) {}
    static all(promiseArr) {}
    static race(promiseArr) {}
}

Promise 內(nèi)部維護著三種狀態(tài) pending、fulfilledrejected,狀態(tài)只能從 pending 轉(zhuǎn)變到 fulfilled,或從 pending 轉(zhuǎn)變到 rejected 且該轉(zhuǎn)變不可逆。

Promise 主要提供了三個實例方法 then,catch,finally,和4個靜態(tài)方法 resolve,reject,all,race。所有方法都都返回一個Promise對象。

構(gòu)造函數(shù)
    constructor(fn) {
        this.fulfilledQueue = [];
        this.rejectedQueue = [];
        this._status = PENDING;
        this._value  = null;

        // 執(zhí)行成功隊列中的回調(diào)函數(shù)
        const handleFulfilledQueue = () => {
            while(this.fulfilledQueue.length) {
                let fulfiledFn = this.fulfilledQueue.shift();
                fulfiledFn(this._value);
            };
        };
        
        // 執(zhí)行失敗隊列中的回調(diào)函數(shù)
        const handleRejectedQueue = () => {
            while(this.rejectedQueue.length) {
                let rejectedFn = this.rejectedQueue.shift();
                rejectedFn(this._value);
            };
        };

        // 完成狀態(tài)轉(zhuǎn)變,執(zhí)行回調(diào)隊列中的回調(diào)函數(shù)
        const _resolve = (val) => {
            const fn = () => {
                if(this._status !== PENDING) {
                    return;
                }
                if(val instanceof MyPromise) {
                    val.then((res) => {
                        this._status = FULFILLED;
                        this._value = res;
                        handleFulfilledQueue();
                    }, (err) => {
                        this._status = REJECTED;
                        this._value = err;
                        handleRejectedQueue();
                    });
                } else {
                    this._status = FULFILLED;
                    this._value = val;
                    handleFulfilledQueue();
                }
            }
            // 保證promise 回調(diào)函數(shù)一定是在同步任務(wù)之后執(zhí)行;
            setTimeout(fn, 0);
        }
        // 完成狀態(tài)Pending到REJECTED的轉(zhuǎn)變,執(zhí)行rejected隊列中的回調(diào)函數(shù)
        const _reject = (val) => {
            const fn = () => {
                if(this._status !== PENDING) {
                    return;
                }
                this._status = REJECTED;
                this._value = val;
                handleRejectedQueue();
            }
            setTimeout(fn, 0);
        }
        
        try {  // 處理外部傳入函數(shù)執(zhí)行異常
            fn(_resolve, _reject);            
        } catch(e) {
            return _reject(e);
        }
    }

Promise 構(gòu)造函數(shù)接收一個函數(shù)執(zhí)行器作為參數(shù),該執(zhí)行器的兩個參數(shù) _resolve、_reject均為函數(shù)類型,由 Promise 內(nèi)部實現(xiàn)。執(zhí)行器在 Promise 構(gòu)造函數(shù)中被立即執(zhí)行。

注意: MyPromise 使用 Timeout 實現(xiàn)異步,使得 MyPromise 只能添加 macrotask,實際上原生的Promise 是 microtask

then 方法
    then(successFn, failFn) {
        return new MyPromise((resolve, reject) => {
            // 執(zhí)行成功時的回調(diào)函數(shù)
            const handleSucess = (fn) => {
                try {
                    if(typeof fn === "function") {
                        const res = fn(this._value);
                        if(res instanceof MyPromise) {
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        resolve(this._value)
                    }
                } catch(e){
                    reject(e);
                }
            }
            // 執(zhí)行失敗時的回調(diào)函數(shù)
            const handleFail = (fn) => {
                try {
                    if(typeof fn === "function") {
                        const res = fn(this._value);
                        if(res instanceof MyPromise) {
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        reject(this._value);
                    }
                } catch(e) {
                    reject(e);
                }
            }
            switch(this._status){
                case PENDING:       // 異步任務(wù)尚未完成,將回調(diào)函數(shù)推入相應(yīng)隊列
                    this.fulfilledQueue.push(() => {
                        handleSucess(successFn);
                    });
                    this.rejectedQueue.push(() => {
                        handleFail(failFn);
                    });
                    break;
                case FULFILLED:     // 異步任務(wù)成功完成,執(zhí)行成功回調(diào)函數(shù)
                    handleSucess(successFn);
                    break;
                case REJECTED:      // 異步任務(wù)已失敗,執(zhí)行失敗回調(diào)函數(shù)
                    handleFail(failFn);
                    break;
                default:
                    console.log("Promise error status:", this._status);
                    break;
            };
        });
    }

then 方法是 Promise 的一個主要方法,catch 和 finally 都可以用 then 來實現(xiàn)。當(dāng) Promise 的狀態(tài)已經(jīng)流轉(zhuǎn)時,回調(diào)函數(shù)會立即被執(zhí)行,當(dāng) Promise 還處于 Pending 狀態(tài)時,回調(diào)函數(shù)被推入相應(yīng)隊列中等待執(zhí)行。

完整代碼
class MyPromise {
    constructor(fn) {
        this.fulfilledQueue = [];
        this.rejectedQueue = [];
        this._status = PENDING;
        this._value  = null;

        const handleFulfilledQueue = () => {
            while(this.fulfilledQueue.length) {
                let fulfiledFn = this.fulfilledQueue.shift();
                fulfiledFn(this._value);
            };
        };
        const handleRejectedQueue = () => {
            console.log(this.rejectedQueue);
            while(this.rejectedQueue.length) {
                let rejectedFn = this.rejectedQueue.shift();
                rejectedFn(this._value);
            };
        };

        // 完成狀態(tài)轉(zhuǎn)變,執(zhí)行回調(diào)隊列中的回調(diào)函數(shù)
        const _resolve = (val) => {
            const fn = () => {
                if(this._status !== PENDING) {
                    return;
                }
                if(val instanceof MyPromise) {
                    val.then((res) => {
                        this._status = FULFILLED;
                        this._value = res;
                        handleFulfilledQueue();
                    }, (err) => {
                        this._status = REJECTED;
                        this._value = err;
                        handleRejectedQueue();
                    });
                } else {
                    this._status = FULFILLED;
                    this._value = val;
                    handleFulfilledQueue();
                }
            }
            setTimeout(fn, 0);
        }
        // 完成狀態(tài)Pending到REJECTED的轉(zhuǎn)變,執(zhí)行rejected隊列中的回調(diào)函數(shù)
        const _reject = (val) => {
            const fn = () => {
                if(this._status !== PENDING) {
                    return;
                }
                this._status = REJECTED;
                this._value = val;
                handleRejectedQueue();
            }
            setTimeout(fn, 0);
        }
        
        try { // 處理外部傳入函數(shù)執(zhí)行異常
            fn(_resolve, _reject);            
        } catch(e) {
            
            return _reject(e);
        }
    }

    then(successFn, failFn) {
        return new MyPromise((resolve, reject) => {
            // 執(zhí)行成功時的回調(diào)函數(shù)
            const handleSucess = (fn) => {
                try {
                    if(typeof fn === "function") {
                        const res = fn(this._value);
                        if(res instanceof MyPromise) {
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        resolve(this._value)
                    }
                } catch(e){
                    reject(e);
                }
            }
            // 執(zhí)行失敗時的回調(diào)函數(shù)
            const handleFail = (fn) => {
                try {
                    if(typeof fn === "function") {
                        const res = fn(this._value);
                        if(res instanceof MyPromise) {
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        reject(this._value);
                    }
                } catch(e) {
                    reject(e);
                }
            }
            switch(this._status){
                case PENDING:       // 異步任務(wù)尚未完成,將回調(diào)函數(shù)推入相應(yīng)隊列
                    this.fulfilledQueue.push(() => {
                        handleSucess(successFn);
                    });
                    this.rejectedQueue.push(() => {
                        handleFail(failFn);
                    });
                    break;
                case FULFILLED:     // 異步任務(wù)成功完成,執(zhí)行成功回調(diào)函數(shù)
                    handleSucess(successFn);
                    break;
                case REJECTED:      // 異步任務(wù)已失敗,執(zhí)行失敗回調(diào)函數(shù)
                    handleFail(failFn);
                    break;
                default:
                    console.log("Promise error status:", this._status);
                    break;
            };
        });
    }

    catch(failFn) {
        return this.then(null, failFn);
    }

    finally(finalFn){
        return this.then(finalFn, finalFn);
    }

    static resolve(val) {
        if(val instanceof MyPromise) {
            return val;
        } else {
            return new MyPromise((resolve, reject) =>{
                resolve(val);
            });
        }
    }

    static reject(val) {
        return new MyPromise((resolve, reject) => {     
            reject(val);
        });
    }

    static all(promiseArr) {
        return new Promise((resolve, reject) =>{
            const len = promiseArr.length;
            let count = 0;
            let result = [];
            for(let i = 0; i < len; i++) {
                promiseArr[i].then((val) => {
                    count++;
                    result.push[val];
                    if(count === len){
                        resolve(result);
                    }
                }, (err) => {
                    reject(err);
                });
            }
        });
    }

    static race(promiseArr) {
        return new Promise((resolve, reject) =>{
            const len = promiseArr.length;
            for(let i = 0; i < len; i++) {
                promiseArr[i].then((val) => {
                    resolve(val);
                }, (err) => {
                    reject(err);
                });
            }
        });
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103251.html

相關(guān)文章

  • JavaScript 異步

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個接口,可通過...

    tuniutech 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細介紹 HTT...

    rottengeek 評論0 收藏0
  • es6 promise源碼實現(xiàn)

    摘要:執(zhí)行的時候呢即可如何處理鏈?zhǔn)降那冶WC順序每個后面鏈一個對象該對象包含子三個屬性當(dāng)父狀態(tài)改變完畢執(zhí)行完相應(yīng)的的時候呢,拿到子在等待這個子狀態(tài)改變,在執(zhí)行相應(yīng)的。 promise源碼分析 初級入門以及如何使用請看 阮一峰promise對象講解 先上一坨代碼,后面我們要基于這坨代碼來實現(xiàn)自定義promise 原始方法 setTimeout(function(){ var a=100...

    未東興 評論0 收藏0
  • 簡單實現(xiàn) ES6 Promise

    摘要:實現(xiàn)的一個簡單的如果有錯誤的地方,希望大家能夠不吝賜教僅實現(xiàn)及方法最下方有完整代碼開始一個對象接收的是一個這個接收兩個參數(shù)當(dāng)我們在內(nèi)執(zhí)行或的時候,就會調(diào)用內(nèi)定義的和函數(shù)然后,和函數(shù)會改變的狀態(tài)所以它應(yīng)該是像下面這樣的保存值記錄狀態(tài)為,為,為 實現(xiàn)的一個簡單的ES6 Promise(如果有錯誤的地方,希望大家能夠不吝賜教) 僅實現(xiàn)Promise及.then方法最下方有完整代碼 開始 一個...

    zhichangterry 評論0 收藏0
  • 淺析es6-promise源碼

    摘要:主要邏輯本質(zhì)上還是回調(diào)函數(shù)那一套。通過的判斷完成異步和同步的區(qū)分。 主要邏輯: 本質(zhì)上還是回調(diào)函數(shù)那一套。通過_subscribers的判斷完成異步和同步的區(qū)分。通過 resolve,reject -> publish -> invokeCallback -> resolve,reject的遞歸和下一條then的parent是上一條的child來完成then鏈的流轉(zhuǎn) 同步情況...

    fox_soyoung 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<