本篇筆記來自 2020.2.26 六角學院線上研討會,講者為偷米騎巴哥的 Tommy。在這一次講座中,Tommy 老師為大家複習了非同步行為與 Queue 的概念,並接續介紹了使非同步行為依序進行的四種方法。
當我們有 3 個 setTimeout() 時,我們可以使它們按照順序執行;但是當我們有 3 個 AJAX 時,由於變因太多、無法確定各自回傳的時間,因此不一定能照順序執行。
要解決非同步無法依序執行的問題,第一個方法是使用 callback function。
讓非同步依序執行 解法一:callback
三個 setTimeout() 個別用 function 包起來,且各個 function 都帶入一個 callback 參數。

呼叫 function A 時,同時定義 callback 的任務內容,如此一來就可以先印出 'A' 再印出 'OK'。

運用這個原理,就可以把 function B 當作 function A 的 callback,把 function C 當作 function B 的 callback。

但是這種做法一旦遇到太多函式要依序執行時,就會變成 callback hell,將會很難去分辨程式碼。
讓非同步依序執行 解法二:Generator
- 在 function 後面加一個
*,執行時會得到一個generator物件。 - 在 for 迴圈中使用
yield關鍵字:代表暫停,先跳出 function,等之後在 function 外面用函式名稱.next()呼叫時,才會再回到 function 內部繼續執行。 generator物件會帶出done特性arguments: 類陣列物件,可取得所有傳入 function 的參數- 遞迴:在函式裡呼叫函式本身

for 迴圈跑到最後一次時,done 的值為 true:

在 recursion() 中使用 .next() 呼叫函式與遞迴,讓 function A, function B, function C 依序執行:

小結:最後一行,在 generator() 帶入多個函式作為參數,就能依序執行並避免 callback hell。
讓非同步依序執行 解法三:Promise
- 一個封裝
Promise的函式 Promise的 callback function 要帶入兩個參數:resolve(成功時呼叫),以及reject(失敗時呼叫)。

非同步成功時,就會執行 resolve;resolve 執行後,就會執行 .then() 的內容;反過來說,.then() 的執行仰賴 resolve 是否執行。

非同步失敗時,Promise 會執行 reject,reject 必須準備對應的函式,這個函式是針對單一的 Promise,在失敗時執行的方案。
在非同步失敗時執行對應的行為也能用 catch 達成,catch 的意思是,只要其中一個 Promise 沒成功執行,就跳到 catch。

讓非同步依序執行 解法四:async…await
- ES7 語法,要搭配
Promise使用 async+ function:宣告這個函式是非同步await+Promise:依序執行函式- 條件:
async跟await一定要搭配使用,不能只用await卻不用async。

reject 時與 try...catch 搭配使用,reject() 括號內的內容會傳到 catch(e) 的 e 參數,也可以直接在 reject() 括號內放入 Error 物件(JS 原生錯誤物件)。

三個函式非同步失敗時想要不同的錯誤訊息:

實務上使用 XMLHttpRequest 時的寫法:

參考資料
slides 簡報
function*
JavaScript Promise:簡介
JavaScript Promise 全介紹