一步一步實現一個符合PromiseA+規(guī)范的Promise庫(1)

今天我們來自己手寫一個符合PromiseA+規(guī)范的Promise庫。大家是不是很激動呢??

才沒有。。

????我們都知道。在現在的前端開發(fā)中,Promise這個東西基本上所有的開發(fā)中都會用到。

????那必然有些萌新就會問了,Promise到底是個什么東西呢。

????按照規(guī)范來說。Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調函數和事件——更合理和更強大。它由社區(qū)最早提出和實現,ES6 將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象。

????通俗來講。。這個東西就是為了解決我們平常的回調函數,避免回調地獄的一種解決方案。所以說這個東西大家不僅要會用哦,還應該知道他的一些原理。so,我們一起來實現下吧。




接下來我們先看一個簡單的Promise。


????這個就是es6標準中的Promise。我們可以看到,其實Promise就是一個構造函數。

????這個構造函數中只有一個參數。這個參數在Promise/A+規(guī)范中被稱為executor(執(zhí)行者..我覺得叫執(zhí)行器蠻好)。

????因為這個執(zhí)行器是為了執(zhí)行后面的resolve(決定)和reject(拒絕)方法。呃...其實你可以把resolve看作是成功,把reject看做失敗。

????當然了我們還可以根據自己定義的規(guī)則來進行Promise中resolve和reject的調用,不過這是用法,我們這里就當大家會用了。。


????然后我們可以看到,在構造函數的實例p中還有一個then方法。這里我們就要想了,既然是構造函數的實例上哪必然這個函數是掛在到這個構造函數的原型上。

????還有很重要的一點就是我們可以想一下,在Promise中這個Promise的當前狀態(tài)是一個問題。在A+規(guī)范中規(guī)定:一個Promise只有三種狀態(tài),我們看圖


什么意思呢。。

????大致的意思就是說,一個Promise有且僅有(pending->等待,fulfilled->已執(zhí)行,rejected->已拒絕)這三種狀態(tài)中的一種(ps:我曾經看到過一個詞->懸而未決用來形容pending也不錯 :)。

? ? 我們知道了這些,接下來我們就來手動實現一個簡單的。


繼續(xù)。。。。


這里我們要說一下,貌似剛才忘說了。。。


????我們通過這張圖來看一下,當目前的狀態(tài)為pending時。我們可以將pending狀態(tài)改變?yōu)閒ulfilled或者rejected中的一種。然而我們要記住,之前已經提到過Promise的狀態(tài)必須是三種之一。而且,如果一旦成功就不能失敗,一旦失敗就不能成功。

接下來我們依據上面狀態(tài)的描述來繼續(xù)、、、


這里當我們調用resolve和reject的時候我們需要做出狀態(tài)判斷,只有是pending狀態(tài)的時候才可以改變狀態(tài)為其他兩種的任意一種,如果不是:例如


我們處理完了resolve和reject內置的邏輯,這里有一個問題。在開發(fā)中,當Promise的執(zhí)行遇到錯誤時,會直接變成rejected狀態(tài),大家應該都知道,也就是下面的處理。


我們在Promise的執(zhí)行過程中如果捕獲到異常,就可以直接調用reject來結束Promise。

接下來我們看then方法。


這樣我們就實現了一個簡單的Promise(才沒有。。。這才哪到哪),我們來試下效果吧。


別忘了導出我們的Promise。。




我們看到下面的輸出結果,哇?。『眉佑袥]有(才沒有激動),我也實現了一個Promise!

但是!有一個問題,我們是不是弄丟了一個狀態(tài)???

what??哪個??仔細想一下好像是‘pending’丟掉了。。

so?那咋辦。

有人可能會說了,不是出了成功就是失敗嗎,為什么會有等待狀態(tài)呢,我們來思考一下下面的代碼。


????話說Promise應該都是支持異步的吧?就像上面的代碼,異步執(zhí)行resolve的時候我們是不是已經吧值給弄丟了?

????并且我們想一下,弄丟這個值得一段時間是不是就是等待態(tài)也就是‘pending’的時候。。

????所以,我們要怎么處理這個pending呢?

????我們想一下,在executor中的resolve和reject是不是都會吧我們傳入的值,傳到then方法的onfulfilled和onrejected中?另外,我們在then方法中做了對目前Promise的狀態(tài)的判斷。

????所以我們在then方法中去處理‘pending’狀態(tài)。

? ? 怎么去處理呢?我們可以在Promise中掛載兩個數組。


? ? 為什么?這兩個數組的作用是為了記錄pending狀態(tài)下的onfulfilled和onreject函數。我們來看then中的代碼。


我們可以看到在pending狀態(tài)下,這兩個數組分別記錄了各自對應的then的回調函數,并且保存起來。

我們來捋一捋思路。


所以說我們的數組里存的是一個一個的then的回調函數,也就是一個一個function。

所以我們要在resolve和reject方法觸發(fā)的時候,去便利我們的數組并且執(zhí)行其中的方法,并且呢還要把我們成功的原因(self.value)和失敗的原因(self.reason)放到我們的回調方法中去。說了這么多有點繞。。上代碼


這樣就解決了異步的問題。我們再來測試一下。

代碼剛開始運行。

2秒后。。。


這時我們就拿到了異步的值,是不是很開心!(有點,嘿嘿)

再看一下我們寫的全部的代碼:



到這里我們簡單了解了Promise的一小部分原理,并且實現了一個非常簡單的Promise。今天就先寫到這里,在下一章中我們會繼續(xù)了解Promise中的then方法是如何鏈式調用的,以及鏈式調用中的許多坑。。。

好啦,謝謝大家看到這里。感謝。

更新。下一篇文章地址為:一步一步實現一個符合PromiseA+規(guī)范的Promise庫(2)

再次感謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 本文適用的讀者 本文寫給有一定Promise使用經驗的人,如果你還沒有使用過Promise,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,466評論 6 19
  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調函...
    neromous閱讀 8,839評論 1 56
  • 前言 本文旨在簡單講解一下javascript中的Promise對象的概念,特性與簡單的使用方法。并在文末會附上一...
    _暮雨清秋_閱讀 2,325評論 0 3
  • 排版很不友好,抱歉 /* * 實現Promise是根據Promise規(guī)范來的:https://promisesap...
    Egde閱讀 1,564評論 0 0
  • static :靜態(tài)變量:只有未定義時才會聲明,否則值會累加,獲取最近的值操作; 遞歸函數 進入函數,最后有明確值...
    overisover閱讀 469評論 0 0

友情鏈接更多精彩內容