[完結篇] - 理解異步之美 --- promise與async await(三)

2020-12-15 碼農登陸

天下沒有不散的宴席

這個系列到這裡應該就是最後一節了,前兩章著重講了promise,為什麼著重講promise呢?因為在用法上promise要比async await難一些,而且promise本身又不是一個語法糖。沒有掌握的時候用起來就會有很多顧慮,async await卻沒有這種顧慮,用法簡單、語義清晰。下面就要開始學習async await了:

不講講迭代器模式總覺得怪怪的

對於java語言來說,迭代器是一個很基本的模式,list與set結構都內置了迭代器。

但是javascript並沒有這種結果(ps:ES6提供了set,而且也可以實現迭代器),但是我們對這種模式實用的並不是特別多。

迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內部表示。

so:迭代器就是在不暴露對象的內部表示的情況下,能夠遍歷整個元素

核心嘛就是:不暴露內部,可以遍歷內部

下面我們就來實現一個簡單的迭代器

這就符合迭代器模式的特點,並沒有暴露內部的對象,通過next的方法可以遍歷內部對象。說到現在很多人應該還沒理解為什麼要說迭代器。

Generator函數執行後會返回一個迭代器

async函數是Generator的語法糖。

這兩個理由是不是一下子就說明寫迭代器是很有用處的。

書寫一個簡單的Generator函數:

我們執行了一下Generator函數返回一個迭代器。通過next方法,可以阻塞性的去執行Generator的代碼。

一說到阻塞大家就想到同步等待阻塞線程導致頁面十分卡頓,明明不是一件很好的事情,為什麼要用這種東西呢?

下面我們就聊聊這種阻塞性的方式有什麼好處呢?

在Generator函數中,迭代器調用next函數後,會一直執行到有yield標示的位置停止。等待next的下一次調用後,代碼會繼續執行到下個yield表示。沒有yield的話就一執行到最後return的位置(沒有return就會一直執行完所有的代碼,這句話好像是個廢話)。

代碼就像擠牙膏一樣,擠一點出一點擠一點出一點,最後沒有卡頓的地方,一口氣擠到底。

所以說如果實用Generator的方式來處理異步的請求會是怎樣的一種感覺。

如果以這種方式來實現異步的請求會怎樣,

1:有一個標誌代表ajax請求完成。2:當標誌為true時代表ajax執行完成,可以進行下一個事件了。3:當標誌為false代碼ajax還未執行完成,繼續阻塞下面的代碼。4:當第一個標誌為true時,執行next(),然後發現到下一個yield之間有異步的代碼,將標誌設置為false,開始執行ajax的事情,阻塞著後面的內容。5:當ajax完成後把標誌設置為true,開始2的內容做的事情不斷執行著直到整個迭代器完成。

粗俗的while循環實現next的調用是不可取的(畢竟偽代碼)

這種方式讓我們體會到另一種處理異步的方式,就是阻塞時的去執行多個串行的異步任務,這樣可以感受同步的寫法去書寫異步的代碼,也就不會在不合適的時間去拿去異步的產生的數據,你阻塞著線程,你不等他執行完,你取值的操作也做不了呀。

如何實用async await

說到這裡如何使用他們就比較清晰明了了吧

這個時候我們使用async函數來處理異步效果就很清晰了,

我們做了一些事情,然後到一個異步的ajax請求後,等待ajaxGetDataFirst這個異步的事件執行完畢後,開始繼續做一些事情,到了第二個ajax異步請求ajaxGetDataSecond(),開始執行阻塞住函數的執行,等待異步事件執行完畢後就繼續做下面的事情。用await關鍵字的時候就是在告訴下面的代碼,這塊你得給我等著,wait我執行完了才能輪到你 understand?總之await吊極了。

await在什麼時候可以用? 只有在async函數體內部使用,而且這個作用範圍是不可以繼承下去的。

在promise中怎麼使用async函數

await 可以接收一個同步的事情嗎?繼續執行下去不阻塞

async函數的返回值是什麼?

async函數的返回值是一個promise對象,

???? what 返回了一個promise對象。這有啥用呢?請聽下面分析

這就代表著你在執行完所有的異步請求後還可以繼續將你需要的結果用return的方式保存在一個promise對象中。promise的用處是什麼?他好像可以存儲一個值在指定情況下觸發一個回調函數(這個不理解的可以看一下上一篇內容哈)所以這可以幫助我們把內部的異步請求的數據拋出到函數外部來。

下面的使用場景:

在使用場景中,我們有的時候需要異步的一個結果,比如ajax請求的結果,這個時候我們希望得到這個異步的結果怎麼辦?

這個時候await可以幫助我,在執行完異步的操作的時候拿到結果,在拿到結果後順序執行下去。直到return的時候把這個結果 return出去,

以下兩種寫法我們是都可以使用的

這兩種方式都可以等待異步的promise執行完成之後再賦值給result,這個時候,我們返回的a就是一個pending狀態的promise對象,上一章節我們講過了promise的基本原理,後面的操作我就不多提了,所以得到你想要的內容的promsie你就會操作了。

這個時候我們async內的異步操作的結果自然而然的可以拋出到函數外部來使用,可以解決很多的業務的封裝問題了。

async 與 Generator的區別

async 與Generator的區別是什麼?

async是Generator的語法糖,Generator是可以用來實現async的,用Generator來實現async的核心就是實現這種不需next調用自執行的內容,這是我以後要進行學習的(目前時間不是很充裕,打算學好之後出一個特別篇好好實現以下async)

尾聲咯

這一節內容並沒有講很多async的內容,反而是先講了迭代器,再講了Generator,最後對async的使用簡單介紹了一下,這是我在學習async時的順序,async用起來容易、同步的寫法也比較熟悉,but!!!易用的東西往往代表著方法內部蘊含很多你不知道的東西,

這才是我們要挖掘的AV8D!!!!

總結一下

異步的事情我們理解了,異步程序執行的過程,了解了event table,任務隊列,宏任務微任務的執行先後條件。了解了異步promise的用法,promise的實現機制、async的用法,以及衍生出來的迭代器知識。

這一段時間和邊學習邊產出文章,有一種被大家鞭策的感覺,哈哈哈哈哈。鞭策這個詞有點怪怪的,這個過程中我發現學習不能只有興趣,興趣可以幫你研究你喜歡的內容時有無限的動力,上了發條一樣,在你低谷、沒有興趣的時候還需要鞭策來幫你去學習新的不擅長的知識,

以前異步是我掌握最差的部分,在這一個階段的學習我收穫很多不知道身為讀者的你收穫了多少呢? 只有你自己知道了

有結束也有開始

異步的美妙我們就算是先告一段落。

下面的一個巨大的系列章節,我將會對vuer-router源碼進行一個系統的學習,並且隨著學習之中產出文檔喲,算是繼續鞭策和與大家一塊學習。

還是那個熟悉的結束語:

每一個前端coder(boy and girl)你們永遠不是一個人在戰鬥!

相關焦點

  • 理解異步之美--- Promise與async await(一)
    本篇旨在以通俗的語言去解釋題目的內容,還希望各位小夥伴們,能夠通讀下來。如果表達有誤的地方,還望評論區指出~不多嗶嗶,坐穩扶好,發車了~你可能會放出一個怪物異步與同步相比,最難以掌控的就是異步的任務會什麼時候完成和完成之後的回調問題。
  • 壓箱底筆記: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()包裝。
  • 理解異步之美——Promise與async await(二)
    4:通過bind函數將callback柯裡化,使callback執行時調用對應的resolve與reject方法,並執行callback第二段 resolve reject then方法的分析為什麼先說這三個方法。
  • Async/Await有什麼用?
    // 每日前端夜話 第394篇// 正文共:2500 字// 預計閱讀時間:8 分鐘當我第一次看到 async/await 的描述時有點困惑,直到我了解了 async/await 的出處,才領悟到它的價值。
  • 如何正確合理使用 JavaScript async/await
    很明顯,async/await 版本比 promise 版本更容易理解。如果忽略 await 關鍵字,代碼看起來就像任何其他同步語言,比如 Python。在 promise中,異步函數有兩個可能的返回值: resolved 和 rejected。我們可以用 .then() 處理正常情況,用 .catch() 處理異常情況。然而,使用 async/await方式的,錯誤處理可能比較棘手。
  • 8 張圖幫你一步步看清 async/await 和 promise 的執行順序
    說實話,關於js的異步執行順序,宏任務、微任務這些,或者async/await這些慨念已經有非常多的文章寫了。但是怎麼說呢,簡單來說,業務中很少用async,不太懂async呢,研究了一天,感覺懂了,所手癢想寫一篇 ,哈哈畢竟自己學會的知識,如果連表達清楚都做不到,怎麼能指望自己用好它呢?
  • 理解JavaScript 的 async/await
    1. async 和 await 在幹什麼任意一個名稱都是有意義的,先從字面意思來理解。async 是「異步」的簡寫,而 await 可以認為是 async wait 的簡寫。所以應該很好理解 async 用於申明一個 function 是異步的,而 await 用於等待一個異步方法執行完成。
  • async/await 原理及執行順序分析
    之前寫了篇文章《這一次,徹底理解Promise原理》,剖析了Promise的相關原理。我們都知道,Promise解決了回調地獄的問題,但是如果遇到複雜的業務,代碼裡面會包含大量的 then 函數,使得代碼依然不是太容易閱讀。
  • async/await,了解一下?
    因此,在 ES6 中封裝了 Generator 函數的語法糖 async 函數,但是將其定義在了 es7 中。ES7 定義出的 async 函數,終於讓 JavaScript 對於異步操作有了終極解決方案。 Async 函數是 Generator 函數的語法糖。使用 關鍵字 Async 來表示,在函數內部使用 await 來表示異步。
  • 如何用實例掌握Async/Await
    今天讓我們一起來探討如何用實例掌握Async/Await目錄1、簡介(callbacks, promises, async/await)2、實例—貨幣轉換器從2個API’s接收異步數據。然後,我們可以調用promise函數的then()和.catch():then —在 promise完成後運行傳遞給它的回調。
  • 你必須了解的JavaScript關鍵字async和await
    為了能夠理解本文的內容,您需要對promises和generators有一個紮實的理解。這些資源應該能幫助你。Promise 假設我們有如下代碼。在這裡,我用一個Promise包裝一個HTTP請求。此外,async函數總是返回一個Promise。如果出現未捕獲的異常,則返回reject promise,否則將返回resolve promise作為異步函數的返回值。這使我們能夠調用一個async函數,並將其與常規的基於Promise的延續。
  • 從promise讀懂JavaScript異步編程
    從《setTimeout(fn,0)函數剖析JavaScript的執行機制》一文已經說明了同步和異步的區別,而這篇文章將更深入的去理解什麼是JS的異步編程,以及promise,async,await等的使用。從而更好的為前端編程打好堅實的基礎。
  • 代碼詳解:Async/Await優於基礎Promises的7大原因
    函數前有關鍵詞async。關鍵詞await 只能用於async定義的函數之內。任一async函數都能隱式返回promise,其解析值是從該函數返回的任意值(在此指字符串「done」)。2. 上一點意味著不能在代碼頂部使用await,因為它不在async定義的函數範圍之中。
  • 如何在 JS 循環中正確使用 async 與 await
    async 與 await 的使用方式相對簡單。 當你嘗試在循環中使用await時,事情就會變得複雜一些。在本文中,分享一些在如果循環中使用await值得注意的問題。準備一個例子對於這篇文章,假設你想從水果籃中獲取水果的數量。
  • 理解C#中的 async await
    一個老掉牙的話題,園子裡的相關優秀文章已經有很多了,我寫這篇文章完全是想以自己的思維方式來談一談自己的理解。
  • 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教程
    async/await更新的和更清潔的語法是使用async/await關鍵字,async在Python 3.5中引入,用於作為一個協同程序聲明一個函數,就像@asyncio.coroutine裝飾器所做的,通過把它放到函數定義前使它應用於函數: