簡(jiǎn)單的實(shí)現(xiàn)一個(gè)promise

有問(wèn)題或者不足之處麻煩點(diǎn)出,請(qǐng)多包含。
第一步:分析promise
1. 用法
2. 分析結(jié)構(gòu)
promise是一個(gè)構(gòu)造函數(shù),有then和catch兩個(gè)基本的方法,其他還有比如all、race、resolve、reject、finally等。(這里的resolve和reject是指內(nèi)部方法,而不是executor里的倆回調(diào))
3. 分析參數(shù)
①:new 過(guò)程中傳入一個(gè)回調(diào)函數(shù)--executor給promise,回調(diào)函數(shù)里有兩個(gè)參數(shù)(resolve,reject,均是函數(shù))由promise來(lái)定義并傳給executor。resolve和reject調(diào)用時(shí)可傳入?yún)?shù)作為實(shí)例的value,在then的回調(diào)中會(huì)被作為參數(shù)傳入。
②:then可傳入兩個(gè)參數(shù)作為回調(diào),第一個(gè)參數(shù)為resolve時(shí)執(zhí)行的回調(diào),第二個(gè)為reject時(shí)執(zhí)行的回調(diào),回調(diào)的參數(shù)res和err是實(shí)例里的value。catch同理。
4. 分析promise的功能
1. promise的作用是將原本異步方法中的回調(diào)地獄套娃情況變?yōu)殒準(zhǔn)秸{(diào)用,為了保證異步的正確性,then里的回調(diào)會(huì)被放入到微任務(wù)隊(duì)列中,這里可以簡(jiǎn)單的用setTimeout實(shí)現(xiàn)。
2. 前面說(shuō)過(guò)resolve()會(huì)走then里的success回調(diào),reject()會(huì)走then里的fail回調(diào)。
這里有個(gè)問(wèn)題:如何確保能正確調(diào)用對(duì)應(yīng)的函數(shù)呢?
答:條件判斷,創(chuàng)建一個(gè)state用于存儲(chǔ)當(dāng)前狀態(tài),then里通過(guò)判斷state是什么狀態(tài)再調(diào)用對(duì)應(yīng)的回調(diào),這樣就能確保正確性。
3. state默認(rèn)為pending狀態(tài),表示在觸發(fā)事件,拿到數(shù)據(jù)value之前,這里的事件指resolve以及reject。前面說(shuō)過(guò)resolve和reject均是可以傳入?yún)?shù)的,而這個(gè)參數(shù)就是實(shí)例保存的value,因此還需要一個(gè)value存儲(chǔ)回調(diào)的結(jié)果方便傳給后面的then回調(diào)。(異步情況需要另外創(chuàng)建幾個(gè)變量,后面再說(shuō))。另外兩個(gè)狀態(tài)為fulfilled和rejected分別對(duì)應(yīng)resolve和reject執(zhí)行后的狀態(tài)。
5. 那么一個(gè)非常簡(jiǎn)單的promise就應(yīng)該是下面這樣的
1. constructor
constructor中對(duì)數(shù)據(jù)進(jìn)行初始化,以及定義resolve和reject
2. then和catch
setTimeout用于模擬放入異步隊(duì)列
3. 整合
一個(gè)只能處理同步任務(wù)的簡(jiǎn)單promise
6. 拓展升級(jí)
1. 每一個(gè)then或者catch都會(huì)返回一個(gè)promise對(duì)象,因此需要封裝then方法
需要對(duì)每一個(gè)回調(diào)的返回值進(jìn)行判斷,如果是promise類(lèi)則進(jìn)行then調(diào)用resolve(success的返回值),reject同理。如果不是promise類(lèi)型則直接resolve和reject函數(shù)返回值。
2. 支持異步
如果executor里的任務(wù)是一個(gè)異步任務(wù),那么esolve或者reject會(huì)被放入任務(wù)隊(duì)列中,可能會(huì)在then里的回調(diào)執(zhí)行之后再執(zhí)行,此時(shí)的state仍處于pending,會(huì)影響到函數(shù)的正確調(diào)用以及數(shù)據(jù)的正確性。
這里會(huì)有一個(gè)問(wèn)題,按照前面的思路,應(yīng)該是創(chuàng)建一個(gè)實(shí)例的變量用來(lái)存儲(chǔ)回調(diào)。但是在支持了返回promise類(lèi)型后可能會(huì)存在多個(gè)then和catch,所以一個(gè)變量明顯不夠,因此需要?jiǎng)?chuàng)建一個(gè)隊(duì)列用于存放回調(diào)(這里我創(chuàng)建兩個(gè)隊(duì)列,一個(gè)成功隊(duì)列,另一個(gè)失敗隊(duì)列)。
前面說(shuō)到then中的state可能為pending,那么就應(yīng)該加一個(gè)判斷,如果是pending就將回調(diào)放入到異步隊(duì)列中。
這里又有一個(gè)問(wèn)題,隊(duì)列是有了,那么該在哪執(zhí)行這些回調(diào)?
答:在resolve和reject中,前面說(shuō)過(guò),只有狀態(tài)改變了回調(diào)才會(huì)執(zhí)行,所以resolve/reject中改變狀態(tài)后就可以執(zhí)行隊(duì)列了。
以下為重寫(xiě)后的constructor
以下為重寫(xiě)的then
3. 支持all和race
①:all的實(shí)現(xiàn),all需要傳入一個(gè)Promise[],當(dāng)所有promise元素都執(zhí)行完后返回一組數(shù)據(jù),當(dāng)有一個(gè)失敗時(shí)則返回失敗原因。
②:race實(shí)現(xiàn):race和all差不多,不同點(diǎn)在于all需要等待所有的promise都執(zhí)行then,而race只需要最快的那個(gè)就行。
4. 支持resolve和reject
直接返回一個(gè)promise對(duì)象
7. 最終版
不足之處麻煩指出,謝謝。