promise

美團(tuán)實(shí)現(xiàn)的promise源碼分析

原文寫的有點(diǎn)繁瑣漠趁,下面是它的代碼加上直接看時(shí)候的理解分析 原文地址
promise有幾個(gè)要點(diǎn)要注意:

  1. 每個(gè)promise對象都有一個(gè)value值闯割,它就是 傳遞給.then注冊函數(shù)的的參數(shù)值
  2. then函數(shù)返回一個(gè)新的promise對象
  3. then的參數(shù)為兩個(gè)函數(shù) onFulfilled, onrejected 以onFulfilled舉例溜徙,如果onFulfilled這個(gè)函數(shù)返回的是一個(gè)普通的值時(shí)嘲更, 那么這個(gè)值就直接賦予.then本身返回的這個(gè)promise對象的value值蠢古,如果onFulfilled返回一個(gè)promise對象的時(shí)候, 這個(gè)是最麻煩的處理情況水由,(假設(shè)onFullfilled返回的promise為promiseB, 對應(yīng)的.then返回的promise為promiseC)叶组, 那么必須保證,promiseB的狀態(tài)確定后圆仔,才執(zhí)行promiseC的resolve(即確定promiseC的狀態(tài))垃瞧, 而且promiseB的value要設(shè)置為promiseC的value
  4. 回調(diào)是異步執(zhí)行的
  5. 注意是 每個(gè)then注冊的函數(shù),它的返回值都轉(zhuǎn)為 then生成的promise的resolve參數(shù)

理解好上面幾點(diǎn)坪郭,就可以看下面的分析了

function Promise(fn) {
    var state = 'pending',
        //這個(gè)value記錄的是promise本身值 即用于它.then(onFulfilled)的參數(shù)值
        value = null,
        //記錄它對應(yīng)的異步回調(diào)對象个从,當(dāng)resolve執(zhí)行的時(shí)候,會異步執(zhí)行這些函數(shù)
        deferreds = [];

    //then會將一下符合條件的回調(diào)加入 deferred    
    

    //須知
    /*  new Promise_A_(resolve => resolve()).then(onFulfilled_B_)_C_ 

    最麻煩的是 onFulfilled 返回也返回一個(gè) promise對象 下面討論這種情況

    * 假設(shè)第一個(gè) new Promise 為 Promise A
    * onFulfilled 返回的promise 為 Promise B
    * then 本身返回的Promise 為 Promise C
    * 必須是 A 狀態(tài)確定即執(zhí)行resolve  然后在 B 狀態(tài)確定  然后再是 C狀態(tài)確定
    * 那么如何才能確保上面的流程執(zhí)行歪沃?
    * 由于執(zhí)行resolve狀態(tài)才能確定嗦锐, 那么上面執(zhí)行情況一定是
    * A 中的 resolve 中 調(diào)用 B 的 resolve  B的resolve中 調(diào)用C的resolve
    * 參數(shù)如何傳遞? 利用好promise 里面的value就行
    */


    this.then = function (onFulfilled, onRejected) {

        //每個(gè)then自動返回一個(gè)promise,
        return new Promise(function (resolve, reject) {

        //這里可以獲取 這個(gè)then創(chuàng)建的promise的resolve函數(shù) 因?yàn)樗锩鏁{(diào)用fn(resolve)
        //獲取這個(gè)resolve函數(shù)可以做流程控制 控制這個(gè)resolve什么時(shí)候執(zhí)行 也就是promise C 
        //什么時(shí)候狀態(tài)確定
        //promiseC 什么時(shí)候狀態(tài)確定呢沪曙?它必須在 onFulfilled 返回的promiseB狀態(tài)確定后才能確定
        //由于PromiseB 在PromiseA的 resolve函數(shù)里面執(zhí)行 所以我們暫時(shí)把 onFulfilled 和 這個(gè)resolve
        //保存起來
        //promise中的fn是 立即執(zhí)行的 不用擔(dān)心handle獲取不到數(shù)據(jù)
            handle({
                onFulfilled: onFulfilled || null,
                onRejected: onRejected || null,
                resolve: resolve,
                reject: reject
            });
        });
    };


    //這個(gè)handler是非常重要的奕污,異步里面當(dāng)前promise狀態(tài)確定了以后也直接調(diào)用它
    //之前說了 promsieA 狀態(tài)確定 才執(zhí)行promiseB的then C也同理
    function handle(deferred) {

        //當(dāng)當(dāng)前的promise對象為pendding時(shí)候 直接加入到異步回調(diào)中
        if (state === 'pending') {
            deferreds.push(deferred);
            return;
        }

        //當(dāng)前promise狀態(tài)已經(jīng)確定了話 就直接執(zhí)行then參數(shù)函數(shù),當(dāng)然如果存在話
        var cb = state === 'fulfilled' ? deferred.onFulfilled : deferred.onRejected,
            ret;
        //這里是非常巧妙的 如果then參數(shù)不處理的話液走,自動交給then返回的promise對象處理
        //起到冒泡的作用
        if (cb === null) {
            cb = state === 'fulfilled' ? deferred.resolve : deferred.reject;
            //如果then參數(shù)不出來 那么之前把promiseA的value復(fù)制給promiseC的resolve
            cb(value);
            return;
        }
        
        //如果then的參數(shù)處理了 比如onFulfilled
        //那么把onFuillfilled的返回值 當(dāng)成value傳遞給promiseC
        //這個(gè)返回值 分為兩種情況 一種為 promsie 一種為 普通值
        //如果為promise的話 那么必須等待這個(gè)promiseB狀態(tài)確定后 promiseC才執(zhí)行它的resolve
        ret = cb(value);
        deferred.resolve(ret);
    }
     //執(zhí)行resolve即能確定自己的狀態(tài)
    function resolve(newValue) {
         //如果它的參數(shù)是promise的話
        if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            var then = newValue.then;
            if (typeof then === 'function') {
                //如果resolve參數(shù)為promise對象的話碳默,那么先確定參數(shù)的promise狀態(tài)贾陷,然
                //后在確定自己本身的promise狀態(tài),
               // 這里就做到了流程控制嘱根,而且把自己本身的resolve髓废,reject傳遞在      
               //newValue的 then函數(shù),恰好還能接受newValue這個(gè)promse的內(nèi)置value该抒,
               //這樣就既做到了流程控制慌洪,又十分巧妙的獲取了promsie的value

                then.call(newValue, resolve, reject);
                return;
            }
        }

        //如果不是promise對象的話, 直接調(diào)用異步回調(diào) 而且設(shè)置promise對象的value
        state = 'fulfilled';
        value = newValue;
        finale();
    }

    function reject(reason) {
        state = 'rejected';
        value = reason;
        finale();
    }

    function finale() {

        // resolve后執(zhí)行的回調(diào) 必須異步的
        setTimeout(function () {
            deferreds.forEach(function (deferred) {
                handle(deferred);
            });
        }, 0);
    }

    fn(resolve, reject);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凑保,隨后出現(xiàn)的幾起案子冈爹,更是在濱河造成了極大的恐慌,老刑警劉巖欧引,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件频伤,死亡現(xiàn)場離奇詭異,居然都是意外死亡维咸,警方通過查閱死者的電腦和手機(jī)剂买,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來癌蓖,“玉大人瞬哼,你說我怎么就攤上這事∽飧保” “怎么了坐慰?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長用僧。 經(jīng)常有香客問我结胀,道長,這世上最難降的妖魔是什么责循? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任糟港,我火速辦了婚禮,結(jié)果婚禮上院仿,老公的妹妹穿的比我還像新娘秸抚。我一直安慰自己,他們只是感情好歹垫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布剥汤。 她就那樣靜靜地躺著,像睡著了一般排惨。 火紅的嫁衣襯著肌膚如雪吭敢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天暮芭,我揣著相機(jī)與錄音鹿驼,去河邊找鬼欲低。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蠢沿,可吹牛的內(nèi)容都是我干的伸头。 我是一名探鬼主播匾效,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼舷蟀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了面哼?” 一聲冷哼從身側(cè)響起野宜,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎魔策,沒想到半個(gè)月后匈子,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闯袒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年虎敦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片政敢。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡其徙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出喷户,到底是詐尸還是另有隱情唾那,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布褪尝,位于F島的核電站闹获,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏河哑。R本人自食惡果不足惜避诽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望璃谨。 院中可真熱鬧沙庐,春花似錦、人聲如沸睬罗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽容达。三九已至古涧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間花盐,已是汗流浹背羡滑。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工菇爪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柒昏。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓凳宙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親职祷。 傳聞我的和親對象是個(gè)殘疾皇子氏涩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容