一步一步實現一個符合PromiseA+規範的Promise庫(3)

xjylyh發表於2018-03-26

日常先打個招呼。。

clipboard.png

今天我們就來完整的實現之前還留有一些小的方法沒實現的Promise。。

回顧:一步一步實現一個符合PromiseA+規範的Promise庫(1)

一步一步實現一個符合PromiseA+規範的Promise庫(2)

我們都知道,Promise中的常用方法有then、catch、Promise.resolve、Promise.reject、Promise.all、Promise.race這些常用方法,接下來我們就一一來實現它們。

先來實現.catch方法。

我們來看以下程式碼

clipboard.png

我們這裡使用的是es6原生的Promise,看到在catch拿到了reject的結果。而且我們看到,在then方法中只有onfulfilled一個回掉函式。

而且,catch方法是支援鏈式呼叫的,so。。我們需要把這個方法掛載到我們的Promise上。

clipboard.png

這樣我們就實現了Promise中的catch方法,是不是很簡單。

可以從之前的測試中看到,.catch方法中的引數只有一個回掉函式,這個回掉函式中有一個引數。我們不難看出來,不管怎樣,這個catch方法拿到的總是我們程式onrejected狀態下的值。所以我們return一個then方法而且只給這個then方法onrejected回撥。then方法中onfulfilled狀態我們傳了一個null,為什麼?其實我們前面有講到過,請參考我上一篇文章: 一步一步實現一個符合PromiseA+規範的Promise庫(2)中的onfulfilled和onrejected預設值的問題。這裡我們就不再贅述了。

我們再來看看Promose.resolve和Promise.reject這兩個方法。

clipboard.png

額。。其實這兩個方法也就是分別返回一個成功和失敗的Promise。這兩個方法作為靜態方法直接掛在到Promise上即可。

接下來我們實現Promise.all方法。

我們知道Promise.all這個方法是處理多個Promise組成的陣列並且返回一個Promise,當全部的Promise處理完畢後在我們下次呼叫then方法時將這個處理結果的陣列返回。我們看下下面的程式碼。

clipboard.png
Promise.all用法

所以我們可以根據這個原理,來實現我們的Promise.all方法。

我們來看以下程式碼。

clipboard.png

額。。我覺得已經蠻清楚了,再捋一捋。

拿到引數Promise陣列->遍歷執行(呼叫其then方法)->存放到返回陣列中->判斷執行是否完畢(完畢:返回我們的陣列)。

clipboard.png

今天有些晚了,就先實現這幾個吧。race方法等明天或者有空吧。然後我們再來分享下javascript的非同步發展流程。。

最初的callback->Promise->generator函式->我們現在常用的 async await

就醬:)

clipboard.png

更新

race方法的實現。

Promise.race這個方法很有意思。。這個方法也是跟all方法一樣接受一個Promise組成的陣列,但是這些個Promise只要有一個成功了,我們的race方法也就執行完畢了,並且返回Promise的執行結果。我們先來看下用法。

clipboard.png

我們看到這裡race方法中有一個Promise陣列,不過只返回了一個結果。並且這個race方法也返回了一個Promise,因為我們在接下來的then方法中拿到了之前的執行結果。so。我們來實現下。

clipboard.png

我們可以看到,在迴圈中我們直接呼叫了傳進來的那些Promise,然後當成功時會直接呼叫我們返回的Promise的resolve方法把執行的結果返回出去。

到這裡我們基本上就實現了一個比較完整的Promise,當然這個Promise還相對簡單。不過我們也蠻不錯了。

clipboard.png

接下來我們看一下js的非同步發展流程.

我們都知道以前比如說我們在處理非同步的時候通常會有這樣的程式碼。

回撥函式

如果{

    我是說{

            能不能{

                        幹一件事{

                         }

            }

    }
複製程式碼

}

醜的一批。。

。。其實也還好,主要是還蠻好看的。但是如果我們非同步做的多了,回撥地獄自然不可避免。所以Promise應運而生。

我們再來看下Promise

一般的程式碼是這樣

Promise.resolve().then().then()......

then多了也不咋好看。。而且一個then中兩個回撥,再返回Promise。。EMMMMM。。

然後出現的就是我們的generator函式。

generator

clipboard.png

如果用過generator函式的小夥伴們應該知道。generator可以在執行過程中多次返回,所以它看上去就像一個可以記住執行狀態的函式,generator函式通常配合Promise和tj寫的co庫來使用。由於generator函式會產生一個執行器,我們要使用這個執行器的next方法來執行我們的非同步方法去得到我們想要的值。

如果有些小夥伴還不明白generator的工作方式,可以去看一下他的使用方法。->Generator 函式的含義與用法

co庫可以幫助我們不去管執行器中的next方法,返回一個Promise並且把執行結果放到返回的Promise的then方法中。

我們可以自己實現一個co庫,其實也是很簡單的一個方法。

clipboard.png

我們看一下測試結果

clipboard.png

發現依舊是沒有問題的。這樣我們就寫了一個簡單的co庫來幫助我們使用generator函式。

最後一個就是我們的async和await。

async-await

clipboard.png

我們可以看到,async和await,使用起來跟generator函式類似,其實呢,async和await就是generator和yield的一種語法糖,

當然這個語法糖的實現比較複雜,我們如果有時間的話還會跟大家一起實現一下。我們這裡先看看他的用法。

我們可以看到,async方法一樣的返回了一個Promise,並且相當於自動執行了generator中的next方法,使得我們不必再耗費精力去處理執行器,在開發中使我們的開發體驗變好了許多。。畢竟程式碼還是簡潔明瞭好一點。。。

clipboard.png

好了,一路走來我們也算比較完整的瞭解了Promise的實現原理,我們也算是完成了一個符合Promise/A+規範的Promise庫。然後我們還了解了js近些年來的非同步發展,有沒有覺得自己很棒呢。。(反正我是覺得我們蠻厲害)

最後,希望大家不管是生活還是學習和工作中都可以更好。再次感謝大家可以看到這裡,謝謝。

就醬,Bye~

clipboard.png

相關文章