理解異步之美——Promise與async await(二)

2020-12-15 碼農登陸

承上啟下

經歷了上一篇基礎的Promise講解後我覺得大家對於promise的基本用法和想法就有一定了解了。(就是一種承諾喲)

下面我們要去了解一下它的工作流程。

結合源碼與分析別人的常見實現進行理解

下面是別人實現的總源碼,(簡單一看就可以)

這是網上一份常見的Promise的源碼實現我會對這個進行一個分析。

(肯定有人問為什麼不自己實現一個? 解:省時、網上太多了、本質還是要了解思想)

話不多說開始咯

咱們先大體梳理一下實現的東西要能幹什麼?

first :

根據這個構造函數,我們需要實現兩個方法,resolve、reject方法

second :

我們要實現一個then方法,可以去根據不同狀態來執行不同的函數。

最基本的兩個內容我們已經確定了。

分析代碼

對代碼的分析在內容的注釋上大家不要遺漏哈!!!

第一段構造函數與狀態設定

自己實現與官方Promise執行的對比。大家可以看一下這個setTimeout導致的執行順序問題。所以閱讀別人對各種功能實現時要學會對照的去看。

到這裡夥伴們已經了解了我們new 一個構造函數時都會做哪些事情。

1:對promise實例定義一個狀態,值為PENDING。2:給promise實例定義一個存放值的空間。3:設置一個發布列表,在以後的指定時間發布其中的事件。4:通過bind函數將callback柯裡化,使callback執行時調用對應的resolve與reject方法,並執行callback

第二段 resolve reject then方法的分析

為什麼先說這三個方法。

因為resolve、reject是核心方法,不說都不行,可是resolve與reject完成要做的事情必須是then方法指定的所以三個方法之間關係密切。

到這裡我們大體梳理清楚,resolve、reject、then方法的用處。

提一嘴 reject方法沒有執行done函數會導致以下情況

一:在new promise實例過程中執行的callback函數,在函數執行的過程中肯定會調用resolve或者reject(兩個都調用也可能)。當調用了resolve方法之後會改變promise的狀態,存放結果。表示任務完成,執行done函數。(reject就不再來一遍了)

二:then方法的執行事件與resolve方法沒有任何先後順序可言。隨心所欲誰在前面都不一定。在resolve(reject)之前執行,就註冊一下要執行的事件。在resolve(reject)之後執行就直接執行就可以了,並且不要註冊。

第三段 具體是怎麼執行的呢?聊聊done與handle

同學們按照代碼執行的順序,我們應該先去看done方法。然後再看handle所以辛苦一下,先向下一點找到可愛的done方法。

這一段我已經把handle與done方法說完了。主要是為了鏈式調用。才會設計的這樣子。所以鏈式調用還是很搶手的一個功能。

自己也可以嘗試的去實現一下符合promise規範的promise功能。

親! 學習完要思考

不知道看到這裡大家對網上常見的promise源碼實現有一種什麼樣的感覺???

我先說說我的感覺

看過源碼(抱歉我的智商是在有限,短時間內是真的看不懂啊),覺得源碼做的要合理太多了。看不懂我都覺得合理。。。。不是對強者的過分崇拜,而是真的很合理。網上常見的實現,只是單單的實現了功能,這樣的promise只適合有一定promise經驗並且守規矩的人使用。為什麼這麼說???

一:這樣實現的promise,狀態可以隨時人為的更改,對外暴露,沒有設置為私有屬性。二:為了方便,選擇把方法設置在原型鏈上,導致無法使用私用變量。三:reject的執行不足,只是對resolve進行合理的使用。雖然我這麼說,我也實現不出來,寫出這些的人還是比我厲害很多。promise的源碼則是(某個版本的,版本號我不記得了)把resolve、reject、all、race,handle方法,都放在構造函數內。把catch、then、chain方法放在原型上。

有圖為證,字面意思應該是這個意思,我覺得我沒想錯。

在改變promise的狀態也好、value也好。都在頻繁的使用PromiseSet方法來設置屬性,對方法進行封裝,並且方便狀態的管理,附加合理的容錯。

對比源碼之後,覺得自己雖然流程大體了解,但是這種精密而且優雅的方式,是短時間內很難去掌握的。promise的源碼當然會堅持看下去,網上能把promise按照規範實現一遍的人已經很厲害了。我雖然覺得還有地方可以修改,但是我比他們還差得遠(這種感覺就有點像:我不上,我就比比),要向他們學習,照這他們去努力。

別說了 喝雞湯吧

前端的學習之路還很漫長,我看過的(僅僅是看過的)源碼半隻手就都數的過來。還是堅信堅持下去,自己就變得很棒。每個人都是從控制流語句學過來的,邏輯也不過是複雜的控制流程(還涉及高端的算法與設計模式),堅信自己一定可以成功!!!一起努力吧 每一個前端er(boy and girl)。所以一切源碼層面看不懂、不理解都可以歸結為看得少、想得少、理解的少。(和你的智商沒有任何關係喲)

下期預告

下一篇就是理解異步之美的終點篇了。異步的美好在於這種神奇的思想。抓住思想的尾巴,不被技術束縛,嘿嘿嘿。

要開新課題了。課題應該是圍繞著vue-router的源碼進行學習。一個與大家分享學習過程的周期性文章。盡情期待!!!

相關焦點

  • [完結篇] - 理解異步之美 --- promise與async await(三)
    天下沒有不散的宴席這個系列到這裡應該就是最後一節了,前兩章著重講了promise,為什麼著重講promise呢?因為在用法上promise要比async await難一些,而且promise本身又不是一個語法糖。沒有掌握的時候用起來就會有很多顧慮,async await卻沒有這種顧慮,用法簡單、語義清晰。
  • 理解異步之美--- Promise與async await(一)
    如果表達有誤的地方,還望評論區指出~不多嗶嗶,坐穩扶好,發車了~你可能會放出一個怪物異步與同步相比,最難以掌控的就是異步的任務會什麼時候完成和完成之後的回調問題。then方法的返回值不是一個promise對象就會被包裝成一個promise對象,所以then方法支持鏈式調用。then方法的鏈式調用可以幫我們串行的解決一些邏輯,當我們平時書寫有順序的異步時間,比如如果使用then的鏈式調用呢?
  • 壓箱底筆記:Promise和Async/await的理解和使用
    2.1 理解抽象表達:Promise 是JS中進行異步編程的新的解決方案(舊的是誰?)5. async與awaitAsync/await 實際上只是一種基於promises的糖衣語法糖,Async/await 和 promises一樣,都是非堵塞式的,Async/await 讓異步代碼更具同步代碼風格,這也是其優勢所在。
  • javascript解決異步async、await和co庫的實現
    相信大家都聽說過js中的回調地獄給代碼維護帶來了很大的阻礙,應用而生的也給出了N解決方案,從最初的promise,到co庫,再到es規範提供的api async、await等!接下來咱們聊的話題就是async和co庫的具體實現在學習前咱們了解幾個小知識點吧!
  • JavaScript中的async/await的用法和理解
    ,可能有錯誤之處,也歡迎指出。今天就說一說「JavaScript中的async/await的用法和理解」程式語言中任意一個關鍵字都是有意義的,我們先從字面意思來理解。1.async async 是「異步」的簡寫,帶async關鍵字的函數,是聲明異步函數,返回值是promise對象,如果async關鍵字函數返回的不是promise,會自動用Promise.resolve()包裝。
  • Async/Await有什麼用?
    .*/)本文中的這類注釋可以幫你理解代碼的執行順序。永遠返回 Promise現在我們知道異步函數不是什麼,但是它們是什麼呢?異步函數的第一個超級功能:總是返回一個 promise。Await異步函數總是返回 promise。要知道為什麼總是返回 Promise,就需要了解異步函數的第二種超級功能:使用 await 語句實現 promise 的能力。在異步函數中編寫代碼時,可以使用 await 語句。該語句在異步函數外部不可用。
  • 如何正確合理使用 JavaScript async/await
    async 函數調用不會造成阻塞,它內部所有的阻塞都被封裝在一個 Promise 對象中異步執行。async/await 帶給我們的最重要的好處是同步編程風格。讓我們看一個例子:很明顯,async/await 版本比 promise 版本更容易理解。如果忽略 await 關鍵字,代碼看起來就像任何其他同步語言,比如 Python。
  • 理解JavaScript 的 async/await
    1. async 和 await 在幹什麼任意一個名稱都是有意義的,先從字面意思來理解。async 是「異步」的簡寫,而 await 可以認為是 async wait 的簡寫。所以應該很好理解 async 用於申明一個 function 是異步的,而 await 用於等待一個異步方法執行完成。
  • async/await,了解一下?
    因此,在 ES6 中封裝了 Generator 函數的語法糖 async 函數,但是將其定義在了 es7 中。ES7 定義出的 async 函數,終於讓 JavaScript 對於異步操作有了終極解決方案。 Async 函數是 Generator 函數的語法糖。使用 關鍵字 Async 來表示,在函數內部使用 await 來表示異步。
  • async/await 原理及執行順序分析
    基於這個原因,ES7 引入了 async/await,這是 JavaScript 異步編程的一個重大改進,提供了在不阻塞主線程的情況下使用同步代碼實現異步訪問資源的能力,並且使得代碼邏輯更加清晰,而且還支持 try-catch 來捕獲異常,非常符合人的線性思維。所以,要研究一下如何實現 async/await。
  • 8 張圖幫你一步步看清 async/await 和 promise 的執行順序
    說實話,關於js的異步執行順序,宏任務、微任務這些,或者async/await這些慨念已經有非常多的文章寫了。但是怎麼說呢,簡單來說,業務中很少用async,不太懂async呢,研究了一天,感覺懂了,所手癢想寫一篇 ,哈哈畢竟自己學會的知識,如果連表達清楚都做不到,怎麼能指望自己用好它呢?
  • 代碼詳解:Async/Await優於基礎Promises的7大原因
    函數前有關鍵詞async。關鍵詞await 只能用於async定義的函數之內。任一async函數都能隱式返回promise,其解析值是從該函數返回的任意值(在此指字符串「done」)。2. 上一點意味著不能在代碼頂部使用await,因為它不在async定義的函數範圍之中。
  • 你必須了解的JavaScript關鍵字async和await
    為了能夠理解本文的內容,您需要對promises和generators有一個紮實的理解。這些資源應該能幫助你。Promise 假設我們有如下代碼。在這裡,我用一個Promise包裝一個HTTP請求。此外,async函數總是返回一個Promise。如果出現未捕獲的異常,則返回reject promise,否則將返回resolve promise作為異步函數的返回值。這使我們能夠調用一個async函數,並將其與常規的基於Promise的延續。
  • 如何用實例掌握Async/Await
    今天讓我們一起來探討如何用實例掌握Async/Await目錄1、簡介(callbacks, promises, async/await)2、實例—貨幣轉換器從2個API’s接收異步數據。然後,我們可以調用promise函數的then()和.catch():then —在 promise完成後運行傳遞給它的回調。
  • 從promise讀懂JavaScript異步編程
    從《setTimeout(fn,0)函數剖析JavaScript的執行機制》一文已經說明了同步和異步的區別,而這篇文章將更深入的去理解什麼是JS的異步編程,以及promise,async,await等的使用。從而更好的為前端編程打好堅實的基礎。
  • 如何在 JS 循環中正確使用 async 與 await
    和getNumFruit來獲取異步函數中每個水果的數量。在 map 中使用 await如果在map中使用await, map 始終返回promise數組,這是因為異步函數總是返回promise。當在filter 回調中使用await時,回調總是一個promise。由於promise 總是真的,數組中的所有項都通過filter 。
  • 理解C#中的 async await
    (PS:文中涉及到了大量反編譯源碼,需要靜下心來細細品味)1|0從簡單開始為了更容易理解這個問題,我們舉一個簡單的例子:用異步的方式在控制臺上分兩步輸出「Hello World!」竟然有兩個 Main 方法:一個同步、一個異步。原來,雖然我們寫代碼時為了在 Main 方法中方便異步等待,將 void Main 改寫成了async Task Main,但是實際上程序入口仍是我們熟悉的那個 void Main。
  • Async:簡潔優雅的異步之道
    另外,這裡分開了每個異步操作,並規定好各自成功或失敗時傳遞出來的數據,近乎實際開發。1 登堂1.1 形式A函數也是函數,所以具有普通函數該有的性質。不過形式上有兩點不同:一是定義A函數時, function關鍵字前需要有 async關鍵字(意為異步),表示這是個A函數。二是在A函數內部可以使用 await關鍵字(意為等待),表示會將其後面跟隨的結果當成異步操作並等待其完成。
  • 深入async/await知多少
    工作原理      async/await簡單來說只是一個語法糧,它只是告訴編譯器要把這些代碼編譯成一個異步狀態機。那編譯器是怎樣生成其對應的異步代碼的呢?可以通過以下代碼你就能更好地理解。      async/await是一個異步處理模型,但並不能說明所有的async/await都是異步處理;具體要看Awaiter狀態機是由誰觸發的,當上層方法邏輯是同步或IO同步完成的情況那await後面的代碼則由同當前線程觸發執行,如果上層方法是異步完成的情況下則由對應相關異步完成的線程調用;所以async/await也有些情況是同步完成的,只是這種情況在
  • Python async/await教程
    使用異步編程,在等待其他資源響應時,允許代碼處理其他任務。協程Python中的異步函數通常被稱為「協程」,它僅僅是一個採用異步關鍵字或是用@asyncio.coroutine裝飾的函數。兩個函數中的任何一個都將作為協同程序工作並且類型是等效的: