Day10 JavaScript Async/Await

更新於 發佈於 閱讀時間約 9 分鐘


在JavaScript裡面,Async和Await應該是搜尋熱度最高的關鍵字了,因為他們相對複雜。我們一步步討論這件事的歷史 — 它們為什麼出現,解決了什麼問題。

JavaScript的Synchronous(同步)

首先我們必須了解JavaScript執行的基本原則 — synchronous(同步)。大部分的JavaScript程式都是synchronous的,意味著一行程式碼執行完才會再執行下一行。「同步」這個中文其實有點誤導人,程式碼並不是「同時」執行,而是一行接著一行執行。這會導致什麼問題呢?如果有一行程式碼執行的特別久,後續的就會受影響而延後執行。這個概念被稱為blocking(阻塞)。

我們舉例說明:

用Date.now() + 3000(單位是毫秒)作為結束條件,3秒後,整段程式才會達到結束條件。

用Date.now() + 3000(單位是毫秒)作為結束條件,3秒後,整段程式才會達到結束條件。

我們創建一個function,讓它在3秒內持續運作loop,直到時間到才會結束。執行後我們可以看到Console印出的順序是這樣。

我們會看見'Start',接著卡3秒,然後'Sync task finished',最後才是'End'。

我們會看見'Start',接著卡3秒,然後'Sync task finished',最後才是'End'。

這個例子呈現了因為synchronous的特性,console.log(”End”)這一行被blocked(阻塞)了。


如果JavaScript都只能這樣運作,問題就大了。一個網站常常需要等候外部傳資料進來,如果在這期間什麼其他程式碼都不能執行的話,使用者很快就離開了。舉例來說,我們點開instagram貼文,在等待資料期間,需要執行程式來show loading或執行其他動畫等等,這些都需要程式碼在等待的時候能夠正常運作。

換句話說,我們非常需要asynchronous(非同步)的運作方式,也就是在某些情況下,程式碼可以獨立運作,其他人不用等它結束才能行動。

但同時,我們也需要保留synchronous的運作方式,想像一下instagram至少要等到你的資料到齊了,才能執行「顯示出貼文」這段程式碼。所以我們需要一些方式來達成「那些是需要非同步的,這些不用」的機制。

Asynchronous的解決方案

JavaScript中做到asynchronous的方法不少,而且經歷了幾個階段,asyncawait就是其中比較近期的。我們會依照時間線來介紹這些方法以及他們為何被取代。


Callback Function(回調函數)

又一個新的function名稱,但別緊張。callback function指的就是「在某件事發生之後,再執行的function」,我們以前就看過。

raw-image

’click’之類的事件發生後,再執行的function就是callback function。


監聽一個事件還好,但如果我們的步驟有4個呢?假設我們需要按照順序讀取4份文件。因為要按照順序,所以我們在每個讀取檔案的function裡加上callback去讀取下一份,看起來會像這樣:

raw-image

你可以想像如果我們有10個步驟要做情況會有多慘烈。一層包著一層的情況非常難理解,而且程式碼本身會變成一個三角形,非常難閱讀。這種情況被稱作callback hell(地獄)。所以callback不是很好的辦法,慢慢有更好的方法出現,那就是Promise


Promise(承諾)

Promise是JavaScript裡面很特殊的物件,它需要用關鍵字new來創造,基礎語法大概是這樣。

raw-image

Promise創建式子裡會有一個function,裡面第一個參數是成功時會做的事,第二的是失敗時會做的事。至於什麼情況會成功跟失敗呢,通常這些都是跟伺服器要求資料的時候會用到的工具,伺服器會回傳成功會失敗的資訊給你。現在的重點是知道它的語法如何勝過callback。


接下來繼續改寫這個例子:

換行只是方便閱讀。

換行只是方便閱讀。

一個Promise後面可以接then()catch(),這些是內建的method。resolve()reject()的參數會被傳過去。以上述的例子來說,當Promise成功,success就會等於”Promise結果成功”。如果失敗fail就會等於”Promise失敗原因”(成功的話catch()就不會執行了)。


這裡一次會看見很多東西,包含之前提過的簡寫arrow function還有chain的概念。在Promise後面接的那些(包含then()catch()),會獨自運行(asynchronous),不會block下面的程式碼。


更重要的是,這個then(),可以寫很多串接下去。我們再討論回剛才讀取書籍,把readFile()改成Promise的版本。

raw-image

在之前我們看見array一直接下去,重點是array必須回傳array才能一直接下去。這裡我們想讓readFilePromise()成為一個chain,就要讓他回傳readFilePromise(),而每個Promise又都有then()可以用,所以可以一直接下去。


從這個改寫範例我們看到,這樣不管寫幾項,程式碼都還是相對好閱讀。Promise雖然已經優化了asynchronous的撰寫,但你也看得出來,它其實也沒那麼好寫,有一堆return和其他關鍵字(不過Promise還是滿常見的)。asyncawait更加簡化了這個流程。


asyncawait

講了這麼久終於到了今天的主題,asyncawait。它們兩個關鍵字的出現讓撰寫非同步程式更像寫同步程式。他們還是需要一個Promise,可以理解成「處理Promise一種更好寫的語法」。

raw-image
raw-image

我們只需要在需要用到asynchronous的function前面加上關鍵字async(非同步)就可以了。async function整個都會獨立運作,不會block其他程式的運行。而裡面的每一行就像synchronous一樣一行一行的運作。第一章內容讀取之後,接著第二章以此類推。


值得注意的是,在回傳Promise的函數前加上await(等待)才可以確保每一步都等候結果再進行,正如同它的字面意思,我們在命令JS等這個Promise完成,這可能更符合邏輯需求。如果不需要按照順序,則可以略過await,讓其他操作繼續運行。

如果那個function跟Promise沒有關係,它本來就會依照順序執行,不用特別加await


總而言之,asyncawait提供了一種更自然的方式來處理asynchronous,更像原本synchronous的寫法。雖然還是有一些學習成本跟額外的規則,像是我們還是需要Promise以及特定位置await的使用等等,但回頭看看callback function,你能了解它的益處。

小結

asyncawait現在已經是相對主流處理asynchronous的方式了,雖然其中還是有些比較不直觀的部分,但比起callback hell和冗長的Promise chain,asyncawait已經提供了一種相對易於閱讀、撰寫的解決方案。今天的內容比較深入,但不用擔心。掌握這些語法的優缺點,理解asyncawait的出現如何簡化了asynchronous,已經是很大的一步了。即使一開始有些不直覺,隨著練習和應用,你會逐漸掌握它們的用法,慢慢進步。


最後,我們會用先前所學的來製作一個簡單的To-Do List App,對於初學JavaScript的人來說,To-Do List真的是一個經典練習。裡面會包含許多關鍵的JS應用,即使是大型的網站產品,也常常需要這些語法。透過這個實作練習,你將會更直觀地體驗JavaScript的實際應用。


Resource

今日Codepen

連結

Credits

關於我

我是Erkin, 一個網站開發者。
有任何疑問或是想勘誤的話歡迎聯繫。

留言
avatar-img
留言分享你的想法!
avatar-img
HCY 71的沙龍
0會員
11內容數
HCY 71的沙龍的其他內容
2024/11/04
這個單元裡我們會繼續用Codepen來製作簡單的To-Do List app。裡面會使用到基本的HTML和CSS來製作UI,別擔心會非常簡單。示範的Codpen同樣會附在今天的內容裡面,如果想看成果的話可以直接點前往。 基礎架構 為了完成這個web app,我們必須先理解HTML、CSS之間
Thumbnail
2024/11/04
這個單元裡我們會繼續用Codepen來製作簡單的To-Do List app。裡面會使用到基本的HTML和CSS來製作UI,別擔心會非常簡單。示範的Codpen同樣會附在今天的內容裡面,如果想看成果的話可以直接點前往。 基礎架構 為了完成這個web app,我們必須先理解HTML、CSS之間
Thumbnail
2024/11/04
今天要談的內容也是JavaScript很核心的部分,即使學完了先前的章節,馬上去看別人寫的JavaScript程式碼還是會看不懂,主要是因為JS開發者會採用各種簡化和替代的寫法,我們一一討論。 Anonymous(匿名) Function 首先我們要討論的是Anonymous(匿名) Fun
Thumbnail
2024/11/04
今天要談的內容也是JavaScript很核心的部分,即使學完了先前的章節,馬上去看別人寫的JavaScript程式碼還是會看不懂,主要是因為JS開發者會採用各種簡化和替代的寫法,我們一一討論。 Anonymous(匿名) Function 首先我們要討論的是Anonymous(匿名) Fun
Thumbnail
2024/11/04
Scope(作用域) 不只是JavaScript,scope的概念在每個程式語言裡面都有,但每個語言scope運作邏輯多少有差異。 我們先來舉個例來了解scope: 隨著myFunction()執行,這段程式毫無疑問的console.log()出了myName這個變數的值’my name’
Thumbnail
2024/11/04
Scope(作用域) 不只是JavaScript,scope的概念在每個程式語言裡面都有,但每個語言scope運作邏輯多少有差異。 我們先來舉個例來了解scope: 隨著myFunction()執行,這段程式毫無疑問的console.log()出了myName這個變數的值’my name’
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
歡迎來到 React 白話文運動第三篇,今天我們將深入探討 JavaScript 中的非同步操作,並介紹兩個重要的關鍵字:Async 與 Await。在這篇文章中,我們將透過實例演示非同步操作的概念,以及如何使用 Promise、Fetch、Async 和 Await 來更有效地處理非同步程式。
Thumbnail
歡迎來到 React 白話文運動第三篇,今天我們將深入探討 JavaScript 中的非同步操作,並介紹兩個重要的關鍵字:Async 與 Await。在這篇文章中,我們將透過實例演示非同步操作的概念,以及如何使用 Promise、Fetch、Async 和 Await 來更有效地處理非同步程式。
Thumbnail
Web Workers主要提供簡單的API讓網頁在背景執行緒中執行程式而不干擾使用者的操作。 javascript主要功能是與user操作頁面互動及操作dom,試想若使用多執行緒的概念,那麼一個動作是新增至某個dom節點,另一個動作則是修改該dom節點,此時瀏覽器應該使用哪個動作為準? 所以為了避免
Thumbnail
Web Workers主要提供簡單的API讓網頁在背景執行緒中執行程式而不干擾使用者的操作。 javascript主要功能是與user操作頁面互動及操作dom,試想若使用多執行緒的概念,那麼一個動作是新增至某個dom節點,另一個動作則是修改該dom節點,此時瀏覽器應該使用哪個動作為準? 所以為了避免
Thumbnail
執行以上程式碼,然後看到了這個結果: 為什麼「延遲0秒」的函式寫在上方,但在console印出的結果,它還是被排在第二順位? 利用AC教材提供的youtube演講連結一窺究竟: 演講提供了更多JS的細節概念,身為JS新手的我還在消化,但若針對教案提出的問題來回答,加上利用google大神查到MDN的
Thumbnail
執行以上程式碼,然後看到了這個結果: 為什麼「延遲0秒」的函式寫在上方,但在console印出的結果,它還是被排在第二順位? 利用AC教材提供的youtube演講連結一窺究竟: 演講提供了更多JS的細節概念,身為JS新手的我還在消化,但若針對教案提出的問題來回答,加上利用google大神查到MDN的
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News