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
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
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
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的
Thumbnail
前言 這是第一次寫技術文章,但其實應該也只能說是蒐集很多資料並學習如何透過自己的話解釋的內容,並不能像其他大神可能分享一些很酷的技術,目標就單純是為了完成最後一週的作業(如下)。 走入非同步之前 執行環境(Execution Context) 執行環境堆疊 (Execution stack)
Thumbnail
前言 這是第一次寫技術文章,但其實應該也只能說是蒐集很多資料並學習如何透過自己的話解釋的內容,並不能像其他大神可能分享一些很酷的技術,目標就單純是為了完成最後一週的作業(如下)。 走入非同步之前 執行環境(Execution Context) 執行環境堆疊 (Execution stack)
Thumbnail
上篇介紹的promise chain的寫法,是已經比原本好維護了沒錯,但是可讀性似乎還是有點不足,其實還可以改成用async/await的寫法,如下: E 其中,async是非同步的意思,等於是把getData()這個function定義為非同步,因此從console可以看到,test是最先被pri
Thumbnail
上篇介紹的promise chain的寫法,是已經比原本好維護了沒錯,但是可讀性似乎還是有點不足,其實還可以改成用async/await的寫法,如下: E 其中,async是非同步的意思,等於是把getData()這個function定義為非同步,因此從console可以看到,test是最先被pri
Thumbnail
promise是ES6才有的,它是一種非同步的技術,使用它除了可以在background處理一些事情以外,還可以增加程式碼的可維護性。
Thumbnail
promise是ES6才有的,它是一種非同步的技術,使用它除了可以在background處理一些事情以外,還可以增加程式碼的可維護性。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News