本篇筆記來自 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 全介紹