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, 一個網站開發者。
有任何疑問或是想勘誤的話歡迎聯繫。

0會員
11內容數
留言0
查看全部
發表第一個留言支持創作者!
HCY 71的沙龍 的其他內容
今天要談的內容也是JavaScript很核心的部分,即使學完了先前的章節,馬上去看別人寫的JavaScript程式碼還是會看不懂,主要是因為JS開發者會採用各種簡化和替代的寫法,我們一一討論。 Anonymous(匿名) Function 首先我們要討論的是Anonymous(匿名) Fun
Scope(作用域) 不只是JavaScript,scope的概念在每個程式語言裡面都有,但每個語言scope運作邏輯多少有差異。 我們先來舉個例來了解scope: 隨著myFunction()執行,這段程式毫無疑問的console.log()出了myName這個變數的值’my name’
在開始討論這兩個陌生的名詞之前,我們先準備一份資料以便後續測試使用。 這筆資料是users的資料,可能是社群平台用來記錄使用者資料的格式。其中users是一個array(有[]包著),裡面包含了3個Object(有{}包著),每個Object內有許多的property-value配對(如id:
Higher-Order Function(高階方程式) 是什麼 Higher-Order Function簡稱HOF,是指一個以function作為參數的function或者回傳function的function,我知道目前聽起來非常抽象,我們舉一個我們之前就已經看過的例子。 以Funct
做選擇的時刻 程式語言中,做選擇是非常常見的一件事。例如:判斷登入者身份是否為管理員、當前設定是否為深色模式等。想像我們有一個交易系統,我們需要判斷使用者帳戶餘額是否足夠購買Apple Vison Pro。首先,我們必須認識if跟else。 if 和 else if跟else是常見的條件判
什麼是Array(陣列) array跟object一樣是一種資料的容器,不同的是array通常用來裝同類別的資料,就像是書架用來收納書。要在書架裡放書跟其他東西也是可以的,但就是有點奇怪,不是大家習慣的做法。 array透過[]宣告。 假設我們要儲存使用者喜歡的顏色這筆資料,每筆資料的類型
今天要談的內容也是JavaScript很核心的部分,即使學完了先前的章節,馬上去看別人寫的JavaScript程式碼還是會看不懂,主要是因為JS開發者會採用各種簡化和替代的寫法,我們一一討論。 Anonymous(匿名) Function 首先我們要討論的是Anonymous(匿名) Fun
Scope(作用域) 不只是JavaScript,scope的概念在每個程式語言裡面都有,但每個語言scope運作邏輯多少有差異。 我們先來舉個例來了解scope: 隨著myFunction()執行,這段程式毫無疑問的console.log()出了myName這個變數的值’my name’
在開始討論這兩個陌生的名詞之前,我們先準備一份資料以便後續測試使用。 這筆資料是users的資料,可能是社群平台用來記錄使用者資料的格式。其中users是一個array(有[]包著),裡面包含了3個Object(有{}包著),每個Object內有許多的property-value配對(如id:
Higher-Order Function(高階方程式) 是什麼 Higher-Order Function簡稱HOF,是指一個以function作為參數的function或者回傳function的function,我知道目前聽起來非常抽象,我們舉一個我們之前就已經看過的例子。 以Funct
做選擇的時刻 程式語言中,做選擇是非常常見的一件事。例如:判斷登入者身份是否為管理員、當前設定是否為深色模式等。想像我們有一個交易系統,我們需要判斷使用者帳戶餘額是否足夠購買Apple Vison Pro。首先,我們必須認識if跟else。 if 和 else if跟else是常見的條件判
什麼是Array(陣列) array跟object一樣是一種資料的容器,不同的是array通常用來裝同類別的資料,就像是書架用來收納書。要在書架裡放書跟其他東西也是可以的,但就是有點奇怪,不是大家習慣的做法。 array透過[]宣告。 假設我們要儲存使用者喜歡的顏色這筆資料,每筆資料的類型
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
JSDoc 全名是 JavaScript Documentation,顧名思義是為 JavaScript 所使用的 API 文件,在程式碼內透過註解的方式撰寫,運行後 JSDoc 會自動掃描註解內容,並生成一份網頁版的文件,對於沒有使用 Typescript 開發的專案,也
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
TypeScript是一種由Microsoft開發和維護的開源編程語言。它是JavaScript的超集,主要擴展了JavaScript的語法,增加了靜態類型檢查和其他特性,使得開發大型應用程序更為方便和可靠。
Thumbnail
在網頁開發中,時間與日期的處理是重要且基礎的部分,本文將介紹 JavaScript 中的日期的處理方法,並提供範例程式來協助你理解。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
JSDoc 全名是 JavaScript Documentation,顧名思義是為 JavaScript 所使用的 API 文件,在程式碼內透過註解的方式撰寫,運行後 JSDoc 會自動掃描註解內容,並生成一份網頁版的文件,對於沒有使用 Typescript 開發的專案,也
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
本章節提供了關於Typescript中流程控制元素的詳細介紹,包括if, else if, else語句,三元運算子,switch語句,各種for迴圈,while迴圈,循環嵌套和控制迴圈語句(break,continue和標籤)的使用。
Thumbnail
TypeScript是一種由Microsoft開發和維護的開源編程語言。它是JavaScript的超集,主要擴展了JavaScript的語法,增加了靜態類型檢查和其他特性,使得開發大型應用程序更為方便和可靠。
Thumbnail
在網頁開發中,時間與日期的處理是重要且基礎的部分,本文將介紹 JavaScript 中的日期的處理方法,並提供範例程式來協助你理解。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協
Thumbnail
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。