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

Hello everybody。我又來啦,還記得咱們上一張實現的內容嗎?前端

clipboard.png

上一張咱們實現了一個簡單的Promise。咱們實現了Promise內部的簡單流程和then方法,而且實現了Promise的異步調用。可是咱們也留下了一些問題。。。異步

因爲今天的代碼是基於上一次咱們實現的內容,因此不甚瞭解的小夥伴們能夠去看我上一篇文章。。async

文章地址:一步一步實現一個符合PromiseA+規範的Promise庫(1)函數

問題一:then方法的鏈式調用測試

咱們都知道,一個Promise是能夠在其中再次返回Promise的(固然也能夠返回一個普通的值)。並且呢,返回的Promise或者返回的普通值咱們須要去拿到它的值而且回傳給咱們下一次的then方法中。好比:spa

clipboard.png

固然咱們也能夠在then方法中返回一個Promise;3d

clipboard.png

因此問題就來了。對象

問題二:若是在then方法中返回Promise或者普通值的狀況,咱們須要怎麼處理。blog

so,開搞。遞歸

咱們先來處理第一個問題,讓咱們的then方法支持鏈式調用,而且能接受普通值。

咱們先來修改then方法中的對於成功狀態(onfulfilled)的判斷,由於下面的跟他是相同的道理。

clipboard.png

這裏咱們首先來看定義的Promise2。爲何要定義這樣一個變量呢?

咱們要知道,若是要實現Promise中then方法的鏈式調用。當第一個then運行完畢而且把返回值給咱們以後,咱們也要返回這個值。

咱們不由要問了?一個值怎麼怎麼會有then方法呢?因此咱們要把這個值包裝成一個Promise對象給返回出去。

因此說,咱們須要使每一個狀態都返回一個Promise。。說的有點多。咱們來測試一下。

clipboard.png

咱們接着改下面兩個狀態。

clipboard.png

咱們來捋一捋。經過測試。

clipboard.png

咱們看到代碼運行了2.496秒,咱們的測試結果是正確的;

到這裏咱們就解決了then方法鏈式調用而且在then方法中返回一個普通值到下一次then方法的成功狀態中。

clipboard.png
是否是感受很爽

接下來咱們解決第二個問題。咱們是須要容許在then方法中返回Promise的。。因此,咱們也要處理這種狀況。

Let us try to do it

clipboard.png
展現一下我深厚的英語功底

其實很簡單,咱們須要一個統一的處理函數來進行在then中返回Promise的處理。。

咱們先新建一個方法叫作resolvePromise(Promise的決定)

clipboard.png

在規範中說道。

clipboard.png

什麼意思呢,就是說若是Promise2和x指向的是同一個對象,咱們這裏就要把須要返回的Promise2置爲reject而且要返回一個類型錯誤。看下面的代碼

clipboard.png
額,就是這樣

而後咱們描述一下細節。。

clipboard.png

clipboard.png

emmmmmmmm...

這TM有點細節。。

好了不逗了,咱們在代碼裏面分析的很清楚了。咱們來捋一捋思路。

在then方法中是能夠返回一個Promise的對吧,而後咱們拿到了then方法的執行結果,也就是多是一個Promise或者是一個普通值(也就是x)。而後咱們對這個x進行判斷,咱們首先要判斷這個x是否是一個Promise對吧。

若是不是咱們能夠直接返回x,若是是的話,咱們應該知道,Promise都會有then方法。咱們接下來就須要判斷這個then方法是否是一個function。若是不是咱們就直接返回這個then的值,emmm...他應給就是一個普通值。

若是這個then方法是一個function咱們就能夠直接去執行他。咱們在兩個回調中進行操做,若是執行的是onfulfilled則咱們進行了關鍵的一步,就是遞歸調用咱們的resolvePromise方法去看咱們的onfulfilled傳進來的參數是否仍是一個Promise,,就這樣一直調用,,直到x或者x.then是一個普通的值爲止,而後咱們就能夠返回這個值,也就是resolve咱們最後的值。

固然咱們這裏加了try{}catch(){}仍是爲了不程序運行中的錯誤。

而後咱們就能夠把咱們以前的狀態判斷中的resolve替換成咱們的resolvePromise方法,例如:

clipboard.png

固然下面的pending狀態也是同樣的。

clipboard.png

到這裏咱們的Promise已經實現的差很少了。可是還有一個問題。咱們思考如下代碼;

clipboard.png

上面代碼用的是ES6的原生的Promise

what?咱們能夠看到,第一個then方法中並無任何東西,然而咱們第二個then中卻拿到了promies中resolve的值。

咱們都知道,then方法中有onfulfilled和onreject兩個回調函數,因此咱們要處理一下這兩個回調函數。

clipboard.png

注意onrejected中的default函數返回是用了throw。由於咱們要返回到下一次的reject中
咱們能夠在then方法中處理一下這兩個回調。判斷一下他們的類型,若是類型是function就表明這兩個回調是有東西的。否則呢咱們就返回一個默認的匿名函數,這個函數的參數就是上一次Promise返回的值,也就是當咱們再次執行onfulfilled或者onrejected的時候就能夠直接拿到這個值了。也就完成了咱們想要的效果。

如今,咱們基本上就實現了一個比較完整地Promise。咱們實現了Promise異步調用,在then方法中返回Promise或者值,實現了then方法中能夠沒有回調函數也能把執行結果傳入下一次的then方法中。

固然咱們基本清楚了Promise的基本原理,之後咱們就能夠說咱們既會使用又能夠實現一個Promise。

clipboard.png

固然還有一些小小的問題,就是Promise中有許多方法咱們沒有實現。例如:

Promise.resolve() . Promise.reject() ..還有.catch()方法 Promise.all()方法等等

在下一篇文章中,咱們會一一的去實現這些方法,而且會介紹一下前端開發這些年的異步發展流程

最初的callback->Promise->generator函數->咱們如今經常使用的 async await

好了,就到這裏吧。看到這裏蠻不容易,謝謝你們。

clipboard.png

相關文章
相關標籤/搜索