摘要:今天我們來(lái)自己手寫(xiě)一個(gè)符合規(guī)范的庫(kù)。是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。我們可以看到,其實(shí)就是一個(gè)構(gòu)造函數(shù)。所以說(shuō)我們的數(shù)組里存的是一個(gè)一個(gè)的的回調(diào)函數(shù),也就是一個(gè)一個(gè)。
今天我們來(lái)自己手寫(xiě)一個(gè)符合PromiseA+規(guī)范的Promise庫(kù)。大家是不是很激動(dòng)呢??
才沒(méi)有。。
我們都知道。在現(xiàn)在的前端開(kāi)發(fā)中,Promise這個(gè)東西基本上所有的開(kāi)發(fā)中都會(huì)用到。
那必然有些萌新就會(huì)問(wèn)了,Promise到底是個(gè)什么東西呢。
按照規(guī)范來(lái)說(shuō)。Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。
通俗來(lái)講。。這個(gè)東西就是為了解決我們平常的回調(diào)函數(shù),避免回調(diào)地獄的一種解決方案。所以說(shuō)這個(gè)東西大家不僅要會(huì)用哦,還應(yīng)該知道他的一些原理。so,我們一起來(lái)實(shí)現(xiàn)下吧。
接下來(lái)我們先看一個(gè)簡(jiǎn)單的Promise。
這個(gè)就是es6標(biāo)準(zhǔn)中的Promise。我們可以看到,其實(shí)Promise就是一個(gè)構(gòu)造函數(shù)。
這個(gè)構(gòu)造函數(shù)中只有一個(gè)參數(shù)。這個(gè)參數(shù)在Promise/A+規(guī)范中被稱為executor(執(zhí)行者..我覺(jué)得叫執(zhí)行器蠻好)。
因?yàn)檫@個(gè)執(zhí)行器是為了執(zhí)行后面的resolve(決定)和reject(拒絕)方法。呃...其實(shí)你可以把resolve看作是成功,把reject看做失敗。
當(dāng)然了我們還可以根據(jù)自己定義的規(guī)則來(lái)進(jìn)行Promise中resolve和reject的調(diào)用,不過(guò)這是用法,我們這里就當(dāng)大家會(huì)用了。。
然后我們可以看到,在構(gòu)造函數(shù)的實(shí)例p中還有一個(gè)then方法。這里我們就要想了,既然是構(gòu)造函數(shù)的實(shí)例上哪必然這個(gè)函數(shù)是掛在到這個(gè)構(gòu)造函數(shù)的原型上。
還有很重要的一點(diǎn)就是我們可以想一下,在Promise中這個(gè)Promise的當(dāng)前狀態(tài)是一個(gè)問(wèn)題。在A+規(guī)范中規(guī)定:一個(gè)Promise只有三種狀態(tài),我們看圖
什么意思呢。。
大致的意思就是說(shuō),一個(gè)Promise有且僅有(pending->等待,fulfilled->已執(zhí)行,rejected->已拒絕)這三種狀態(tài)中的一種(ps:我曾經(jīng)看到過(guò)一個(gè)詞->懸而未決用來(lái)形容pending也不錯(cuò) :)。
我們知道了這些,接下來(lái)我們就來(lái)手動(dòng)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的。
繼續(xù)。。。。
這里我們要說(shuō)一下,貌似剛才忘說(shuō)了。。。
我們通過(guò)這張圖來(lái)看一下,當(dāng)目前的狀態(tài)為pending時(shí)。我們可以將pending狀態(tài)改變?yōu)閒ulfilled或者rejected中的一種。然而我們要記住,之前已經(jīng)提到過(guò)Promise的狀態(tài)必須是三種之一。而且,如果一旦成功就不能失敗,一旦失敗就不能成功。
接下來(lái)我們依據(jù)上面狀態(tài)的描述來(lái)繼續(xù)、、、
這里當(dāng)我們調(diào)用resolve和reject的時(shí)候我們需要做出狀態(tài)判斷,只有是pending狀態(tài)的時(shí)候才可以改變狀態(tài)為其他兩種的任意一種,如果不是:例如
我們處理完了resolve和reject內(nèi)置的邏輯,這里有一個(gè)問(wèn)題。在開(kāi)發(fā)中,當(dāng)Promise的執(zhí)行遇到錯(cuò)誤時(shí),會(huì)直接變成rejected狀態(tài),大家應(yīng)該都知道,也就是下面的處理。
我們?cè)赑romise的執(zhí)行過(guò)程中如果捕獲到異常,就可以直接調(diào)用reject來(lái)結(jié)束Promise。
接下來(lái)我們看then方法。
這樣我們就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Promise(才沒(méi)有。。。這才哪到哪),我們來(lái)試下效果吧。
別忘了導(dǎo)出我們的Promise。。
我們看到下面的輸出結(jié)果,哇!!好激動(dòng)有沒(méi)有(才沒(méi)有激動(dòng)),我也實(shí)現(xiàn)了一個(gè)Promise!
但是!有一個(gè)問(wèn)題,我們是不是弄丟了一個(gè)狀態(tài)???
what??哪個(gè)??仔細(xì)想一下好像是‘pending’丟掉了。。
so?那咋辦。
有人可能會(huì)說(shuō)了,不是出了成功就是失敗嗎,為什么會(huì)有等待狀態(tài)呢,我們來(lái)思考一下下面的代碼。
話說(shuō)Promise應(yīng)該都是支持異步的吧?就像上面的代碼,異步執(zhí)行resolve的時(shí)候我們是不是已經(jīng)吧值給弄丟了?
并且我們想一下,弄丟這個(gè)值得一段時(shí)間是不是就是等待態(tài)也就是‘pending’的時(shí)候。。
所以,我們要怎么處理這個(gè)pending呢?
我們想一下,在executor中的resolve和reject是不是都會(huì)吧我們傳入的值,傳到then方法的onfulfilled和onrejected中?另外,我們?cè)趖hen方法中做了對(duì)目前Promise的狀態(tài)的判斷。
所以我們?cè)趖hen方法中去處理‘pending’狀態(tài)。
怎么去處理呢?我們可以在Promise中掛載兩個(gè)數(shù)組。
為什么?這兩個(gè)數(shù)組的作用是為了記錄pending狀態(tài)下的onfulfilled和onreject函數(shù)。我們來(lái)看then中的代碼。
我們可以看到在pending狀態(tài)下,這兩個(gè)數(shù)組分別記錄了各自對(duì)應(yīng)的then的回調(diào)函數(shù),并且保存起來(lái)。
我們來(lái)捋一捋思路。
所以說(shuō)我們的數(shù)組里存的是一個(gè)一個(gè)的then的回調(diào)函數(shù),也就是一個(gè)一個(gè)function。
所以我們要在resolve和reject方法觸發(fā)的時(shí)候,去便利我們的數(shù)組并且執(zhí)行其中的方法,并且呢還要把我們成功的原因(self.value)和失敗的原因(self.reason)放到我們的回調(diào)方法中去。說(shuō)了這么多有點(diǎn)繞。。上代碼
這樣就解決了異步的問(wèn)題。我們?cè)賮?lái)測(cè)試一下。
代碼剛開(kāi)始運(yùn)行。
2秒后。。。
這時(shí)我們就拿到了異步的值,是不是很開(kāi)心!(有點(diǎn),嘿嘿)
再看一下我們寫(xiě)的全部的代碼:
到這里我們簡(jiǎn)單了解了Promise的一小部分原理,并且實(shí)現(xiàn)了一個(gè)非常簡(jiǎn)單的Promise。今天就先寫(xiě)到這里,在下一章中我們會(huì)繼續(xù)了解Promise中的then方法是如何鏈?zhǔn)秸{(diào)用的,以及鏈?zhǔn)秸{(diào)用中的許多坑。。。
好啦,謝謝大家看到這里。感謝。
再次感謝。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/93584.html
摘要:我們都知道,方法中有和兩個(gè)回調(diào)函數(shù),所以我們要處理一下這兩個(gè)回調(diào)函數(shù)。我們實(shí)現(xiàn)了異步調(diào)用,在方法中返回或者值,實(shí)現(xiàn)了方法中可以沒(méi)有回調(diào)函數(shù)也能把執(zhí)行結(jié)果傳入下一次的方法中。 Hello everybody。我又來(lái)啦,還記得我們上一張實(shí)現(xiàn)的內(nèi)容嗎? showImg(https://segmentfault.com/img/bV6UaU?w=102&h=95); 上一張我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的...
摘要:簡(jiǎn)單實(shí)現(xiàn)前言你可能知道,的任務(wù)執(zhí)行的模式有兩種同步和異步。你已經(jīng)實(shí)現(xiàn)了方法方法是一個(gè)很好用的方法。感興趣的朋友可以自行去研究哈附上代碼完整的實(shí)現(xiàn)個(gè)人博客鏈接 Promise 簡(jiǎn)單實(shí)現(xiàn) 前言 你可能知道,javascript 的任務(wù)執(zhí)行的模式有兩種:同步和異步。 異步模式非常重要,在瀏覽器端,耗時(shí)很長(zhǎng)的操作(例如 ajax 請(qǐng)求)都應(yīng)該異步執(zhí)行,避免瀏覽器失去響應(yīng)。 在異步模式編程中,我...
摘要:不同的的實(shí)現(xiàn)需要可以相互調(diào)用,搞清楚了標(biāo)準(zhǔn)之后,開(kāi)始動(dòng)手吧構(gòu)造函數(shù)產(chǎn)生一個(gè)對(duì)象有很多種方法,構(gòu)造函數(shù)是看起來(lái)最面向?qū)ο蟮囊环N,而且原生實(shí)現(xiàn)也是使用的構(gòu)造函數(shù),因此我也決定使用構(gòu)造函數(shù)的方法。 -- What i cant create, i dont understant 前言 實(shí)現(xiàn)Promise的目的是為了深入的理解Promies,以在項(xiàng)目中游刃有余的使用它。完整的代碼見(jiàn)gitHub...
摘要:以上代碼,可以完美通過(guò)所有用例。在的函數(shù)中,為何需要這個(gè)同樣是因?yàn)橐?guī)范中明確表示因此我們需要這樣的來(lái)確保只會(huì)執(zhí)行一次。其他情況,直接返回以該值為成功狀態(tài)的對(duì)象。 Promise是前端面試中的高頻問(wèn)題,我作為面試官的時(shí)候,問(wèn)Promise的概率超過(guò)90%,據(jù)我所知,大多數(shù)公司,都會(huì)問(wèn)一些關(guān)于Promise的問(wèn)題。如果你能根據(jù)PromiseA+的規(guī)范,寫(xiě)出符合規(guī)范的源碼,那么我想,對(duì)于面試...
摘要:嗝首先,我們通過(guò)字面可以看出來(lái)是一種解決方案,而且還有兩種傳統(tǒng)的解決方案回調(diào)函數(shù)和事件,,那么我們就來(lái)先聊聊這兩種方案。 前言 雖然今年已經(jīng)18年,但是今天還是要繼續(xù)聊聊ES6的東西,ES6已經(jīng)過(guò)去幾年,可是我們對(duì)于ES6的語(yǔ)法究竟是掌握了什么程度,是了解?會(huì)用?還是精通?相信大家和我一樣都對(duì)自己有著一個(gè)提升的心,對(duì)于新玩具可不能僅僅了解,對(duì)于其中的思想才是最吸引人的,所以接下來(lái)會(huì)通過(guò)...
閱讀 3122·2023-04-25 15:02
閱讀 2827·2021-11-23 09:51
閱讀 2039·2021-09-27 13:47
閱讀 1994·2021-09-13 10:33
閱讀 982·2019-08-30 15:54
閱讀 2648·2019-08-30 15:53
閱讀 2864·2019-08-29 13:58
閱讀 898·2019-08-29 13:54