callback 是 事件驅動程式設計 (event-driven programming)
中非常強大的功能。
讓 JavaScript 語言能夠將 callback function 作為參數傳遞給其他函數(像是 JS 中的 addEventListener 和 setTimeout)是很有用的。
在 JavaScript 中,callback 被當成 event loop 監督執行已在佇列中進行的程式的指標。
function 被放進 Async Function (非同步函式) 裡作為參數的話, 稱為 callback
,這些callback function 會被依序放置在 callback queue 等待執行。
doX();
doZ(function() {
doY();
});
Result:
doX() -> doZ() -> doY()
不過 callback 有個缺點就是可能會形成 callback hell (回呼地域)
...
回呼地域(callback hell)還有一個比較具體一點的稱呼, 毀滅金字塔(pyramid of doom)
, 表示層次太深的巢狀 callbacks,過度嵌套太多的 events, callback function 而讓程式架構變得更複雜,難以預測和維護。
doX(function() {
doY();
doZ(function() {
doQ();
});
doF();
});
doC();
Result:
doX() -> doC() -> doY() -> doZ() -> doF() -> doQ()
再看看魔王級別的 callback hell
Credit: https://thecodebarbarian.com/2015/03/20/callback-hell-is-a-myth
是不是滿嚇人的, 不過幸好我們有 Promise, 它可以幫助我們脫離 callback hell 的苦難。
Promise 承諾有兩種: 信守承諾 (fulfill/resolve)、承諾失敗 (reject)。但當在 Promise 承諾的結果展現前,會進入一個不確定到底是成功完成還是失敗的狀態 (pending)。
Promise 是一種契約:
另外, 只能從 Pending 變為 Fulfilled 或 Rejected(沒辦法收回/返回)
舉個簡單的日常生活例子來說, 當你去一家 pizza 餐廳…
Example: 我承諾等一下會回來為您上菜 (by 服務生)
Pending: 等待我的 pizza 上菜…
Fulfilled: Pizza 來了!!
Rejected: 廚房的起司用完了 :(
function | description |
---|---|
let promiseObj = new Promise(executorFn) | 使用 executorFn 創建一個新的 Promise 物件 |
promiseObj.then(onFulfilled, onRejected) | 當 promise 被完成, fulfilled(或是失敗, rejected)時調用 onFulfilled (或是 onRejected) 函數 |
promiseObj.catch(callback) | 如果 promise 失敗(或發生錯誤),則調用 callback 函數 |
function executorFn(resolve, reject) {
// ...
if (conditionMet) {
resolve(); // Passed by the Promise object
} else {
reject(); // Passed by the Promise object
}
}
// 您定義此函數並將其傳遞給 Promise 構造函數 (Promise constructor)