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

資訊專欄INFORMATION COLUMN

promise源碼庫

魏明 / 2769人閱讀

摘要:先直接上源碼吧。阮一峰在基礎(chǔ)篇提到過,阮一峰基礎(chǔ)介紹,返回的是一個新的實例,不是原來的那個實例。同理綁定和的指向。秒后,是為了讓在隊列的最后執(zhí)行。此時將中第一個回調(diào)函數(shù)執(zhí)行的賦值給了。這就驗證了阮一峰在基礎(chǔ)介紹將的下面的代碼邏輯。

先直接上源碼吧。

if(!window.Promise) {
    function Promise(fn) {
        var self=this;
        this.status = "pending";
        this.thenCache = [];
        this.count = 0
        if(!(this instanceof Promise)) {
            throw "Defer is a constructor and should be called width "new" keyword";
        }
        if(typeof fn !== "function") {
            throw "Defer params must be a function";
        }
        //為了讓傳進(jìn)來的函數(shù)在then后執(zhí)行
        setTimeout(function() {
            try {
                fn.call(this, self.resolve.bind(self), self.reject.bind(self))
            } catch(e) {
                self.reject(e);
            }
        }, 0);
    }
    Promise.prototype.resolve = function(value) {
        this.value = value;
        this.status = "resolved";
        this.triggerThen();
    }
    Promise.prototype.reject = function(reason) {
        this.value = reason;
        this.status = "rejected";
        this.triggerThen();
    }
    Promise.prototype.then = function(onResolve, onReject) {
        this.thenCache.push({ onResolve: onResolve, onReject: onReject });
        console.log("this", this)
        return this;
    }
    Promise.prototype.catch = function(fn) {
        if(typeof fn === "function") {
            this.errorHandle = fn;
        }
    };
    Promise.prototype.triggerThen = function() {
        console.log("this.thenCache", this.thenCache)
        console.log("this.status", this.status)
        var current = this.thenCache.shift(),
            res;
        console.log("current", current)
        if(!current && this.status === "resolved") {
            // console.log("--11--", + new Date())
            return this;
        } else if(!current && this.status === "rejected") {
            if(this.errorHandle) {
                this.value = this.errorHandle.call(undefined, this.value);
                this.status = "resolved";
                console.log("--11--", + new Date())
            }
            return this;
        };
        if(this.status === "resolved") {
            // console.log("--222--", + new Date())
            res = current.onResolve;
        } else if(this.status === "rejected") {
            console.log("--222--", + new Date())
            res = current.onReject;
        }
        this.count ++;
        if(typeof res === "function") {
            try {
                this.value = res.call(undefined, this.value);
                this.status = "resolved";
                console.log("-ffffd--", + new Date())
                this.triggerThen();
                // console.log("this.count", this.count, + new Date())
            } catch(e) {
                this.status = "rejected";
                this.value = e;
                return this.triggerThen();
            }
        } else {
            console.log("--44--")
            this.triggerThen();
        }
    }
    window.Promise = Promise;
}

之前寫過如何構(gòu)造一個promise庫,參考的美團(tuán)點評的網(wǎng)站,寫到后面發(fā)現(xiàn)Promise.resolve()直接調(diào)用就會出現(xiàn)問題。報錯上面的庫,也是引用Talking Coder的一篇博客,逐漸開始理解promise內(nèi)部是如何實現(xiàn)的了,當(dāng)然還是有一些疑問。比如上面的庫,需要注釋window.Promise = Promise和if(!window.Promise) {} 內(nèi)部的代碼在debug的時候才能看得見。但如果注釋掉,直接Promise.resolve()又回同樣報resolve不是一個方法。

阮一峰在promise基礎(chǔ)篇提到過,阮一峰promise基礎(chǔ)介紹,then返回的是一個新的Promise實例,不是原來的那個實例。這里提到的原來的那個實例,我想應(yīng)該是第一次實例化的Promise實例對象。這里有點不懂,為何then函數(shù)在return this后,就會返回一個新的Promise實例對象。

大概講解下此Promise庫的原理吧。

setTimeout(function() {
            try {
                fn.call(this, self.resolve.bind(self), self.reject.bind(self))
            } catch(e) {
                self.reject(e);
            }
}, 0);

call 和 bind 都是為了綁定this的指向,因為直接回調(diào),this在瀏覽器里面指向的是window對象,綁定fn執(zhí)行的時候this指向Promise的實例對象。同理綁定resolve和reject的this指向。
setTimout 0秒后,是為了讓fn在隊列的最后執(zhí)行。這里的隊列一會再剖析。或者說讓resolve或reject在隊列的最后執(zhí)行。
如果去掉setTimeout 0秒后,那么在實例化Promise的時候,就會立刻執(zhí)行回調(diào)fn,進(jìn)而執(zhí)行resolve或reject函數(shù),而此時then還未來得及push需要thenAble的回調(diào)隊列,導(dǎo)致再執(zhí)行resolve或reject里面的triggerThen()方法時,無法執(zhí)行(此時回調(diào)隊列為空。)

Promise.prototype.then = function(onResolve, onReject) {
    this.thenCache.push({ onResolve: onResolve, onReject: onReject });
    return this;
}

then 實際是一個回調(diào)隊列,當(dāng)有3個then,那么回調(diào)隊列就會有三個。然后通this.triggerThen()
以此遞歸調(diào)用,直接回調(diào)隊列被調(diào)用完畢后,再執(zhí)行fn中的resolve或reject函數(shù)。

再分析下狀態(tài)和返回值
在triggerThen函數(shù)里有這么幾行代碼

if(typeof res === "function") {
        try {
                this.value = res.call(undefined, this.value);
                this.status = "resolved";
                this.triggerThen();
        } catch(e) {
                this.status = "rejected";
                this.value = e;
                return this.triggerThen();
        }
        } else {
            this.triggerThen();
        }

可以看出,當(dāng)js無語法報錯的時候,執(zhí)行的try代碼。此時將then()中第一個回調(diào)函數(shù)執(zhí)行的value賦值給了this.value。在new Promise()的回調(diào)函數(shù)中,如果執(zhí)行過resolve()的話,那么此時賦值就是第二次賦值了。同理this.status。當(dāng)出現(xiàn)語法報錯的時候,會執(zhí)行catch,此時將錯誤參數(shù)e同樣賦值給this.value。狀態(tài)也被變?yōu)閞ejected。同理如果在new Promise()回調(diào)中執(zhí)行過reject,那么此時賦值也是第二次賦值了。這就驗證了阮一峰在Promise基礎(chǔ)介紹將的下面的代碼邏輯。

const promise = new Promise(function(resolve, reject) {
  throw new Error("test");
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

catch 跟then的第二個參數(shù)是一個邏輯。而且then的第二個參數(shù)實際我們很少回調(diào)。都寫catch來異常捕獲的。

其實寫這篇文章的時候,對Promise還是了解在表面上,但收獲依然還是有的,準(zhǔn)建理解了Promise是如何實現(xiàn)的,比如resolve和then回調(diào)的關(guān)系,

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

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

相關(guān)文章

  • 源碼Promise 概念與實現(xiàn)

    摘要:從源碼看概念與實現(xiàn)是異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問題。這些概念中有趣的地方在于,標(biāo)識狀態(tài)的變量如都是形容詞,用于傳入數(shù)據(jù)的接口如與都是動詞,而用于傳入回調(diào)函數(shù)的接口如及則在語義上用于修飾動詞的副詞。 從源碼看 Promise 概念與實現(xiàn) Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問題。在沒有引入新的語言機(jī)制的前提下,這...

    kel 評論0 收藏0
  • 小而美的Promise——promiz源碼淺析

    摘要:因此,當(dāng)作為參數(shù)的執(zhí)行任意結(jié)果的回調(diào)函數(shù)時,就會將參數(shù)傳遞給外層的,執(zhí)行對應(yīng)的回調(diào)函數(shù)。 背景 在上一篇博客[[譯]前端基礎(chǔ)知識儲備——Promise/A+規(guī)范](https://segmentfault.com/a/11...,我們介紹了Promise/A+規(guī)范的具體條目。在本文中,我們來選擇了promiz,讓大家來看下一個具體的Promise庫的內(nèi)部代碼是如何運作的。 promiz...

    figofuture 評論0 收藏0
  • 深入koa源碼(二):核心原理

    摘要:最近讀了的源碼,理清楚了架構(gòu)設(shè)計與用到的第三方庫。本系列將分為篇,分別介紹的架構(gòu)設(shè)計和個核心庫,最終會手動實現(xiàn)一個簡易的。本文來自心譚博客深入源碼核心庫原理所有系列文章都放在了。這一段邏輯封裝在了核心庫里面。 最近讀了 koa2 的源碼,理清楚了架構(gòu)設(shè)計與用到的第三方庫。本系列將分為 3 篇,分別介紹 koa 的架構(gòu)設(shè)計和 3 個核心庫,最終會手動實現(xiàn)一個簡易的 koa。這是系列第 2...

    tyheist 評論0 收藏0
  • thunkify與co源碼解讀

    開頭 首先本文有將近3000字,閱讀可能會占用你20分鐘左右。 文筆可能不佳,希望能幫助到閱讀此文的人有一些收獲 在進(jìn)行源碼閱讀前首先抱有一個疑問,thunk函數(shù)是什么,thunkify庫又是干什么的,co又是干嘛,它有啥用 程序語言有兩種求值策略 傳名調(diào)用 傳入?yún)?shù)實際上是傳入函數(shù)體 傳值調(diào)用 函數(shù)體在進(jìn)入的時候就進(jìn)行運算計算值 編譯器的傳名調(diào)用實現(xiàn),往往是將參數(shù)放到一個臨時函數(shù)之中,再將這個...

    Tangpj 評論0 收藏0
  • co 函數(shù)

    摘要:參考函數(shù)庫是用于函數(shù)自動執(zhí)行的一個小工具。是一個函數(shù)函數(shù)返回一個函數(shù)執(zhí)行完成上面代碼中,等到函數(shù)執(zhí)行結(jié)束,就會輸出一行提示。函數(shù)其實就是將兩種自動執(zhí)行器函數(shù)和對象,包裝成一個庫。使用的前提是,函數(shù)內(nèi)的命令后面,只能是函數(shù)或者對象。 參考 reference 1 reference 2 co 函數(shù)庫是用于 Generator 函數(shù)自動執(zhí)行的一個小工具。 usge var co = r...

    張紅新 評論0 收藏0

發(fā)表評論

0條評論

魏明

|高級講師

TA的文章

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