不知道大家學習英語的時候有沒有過明明語法規則都記清楚了,卻還是不清楚實際如何運用的經驗,或是只能死記文法書上的句子,遇到變化的情形就不知所措(怎麼好像是要賣英文課程XD)
上述的經驗想必大家或多或少都曾經歷過,而我在學習 Promise 的時候也有同樣的感受。
以下嘗試在認識語法後,用生活實例練習 Promise 的概念
在蹲馬步學習語法前,必須要知道 Promise 的出現是因為過去用callback 方式來處理非同步事件的順序時,程式碼會有過於巢狀難以閱讀及難維護的現象
Promise的串接特性讓原本多層巢狀的程式碼可以變成單層
而在 ES2017 (ES8) 又出現了async/await,整個演化史簡單呈現如下:
callback hell --> Promise --> async/await
知道整個脈絡後一起來看語法吧!
new Promise( /* executor */ function(resolve, reject) { ... } );
根據MDN的語法規則,Promise 物件接受一個callback function,這個 callback function 接受兩個參數:
resolve
函式reject
函式pending
:初始狀態,不是 fulfilled 與 rejected。fulfilled
:表示操作成功完成。rejected
:表示操作失敗
圖片來源:MDN
根據上圖,Promise物件在建立時是處於 pending 的狀態,之後會有以下兩種可能:
這兩個方法都可以回傳 Promise,可以繼續串接。
Promise.prototype.then()
:接收 resolve 函式的結果Promise.prototype.catch()
:用來抓取 reject 函式的錯誤原因看完語法覺得一切支離破碎的話不如一起跟著生活實例練習看看~(以下範例參考 Wes Bos 部落格改寫)
想像我們今天去點飲料,店家會給你收據和叫號單,當號碼輪到你的時候才代表飲料做好了,Promise 的概念就類似於那張叫號單,當我們拿到叫號單的時候,代表我們在未來某一刻會拿到點的飲料。
以下在makeDrinks的函式中回傳一個 Promise,用 setTimeout 模擬等待店家製作飲料的時間。
function makeDrinks(drinksName) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`這是你點的${drinksName}`);
}, 2000);
});
}
// 一張叫號單
const bubbleTeaPromise = makeDrinks("珍珠奶茶");
console.log(bubbleTeaPromise); // 印出一個Promise物件
// 用.then() 取得結果
bubbleTeaPromise.then((drinks) => {
console.log(drinks);
});
// 這是你點的珍珠奶茶
現在模擬店家收到三張訂單,必須依照來電先後順序製作
makeDrinks("珍珠奶茶")
.then((drinks) => {
console.log(drinks);
return makeDrinks("英式紅茶");
})
.then((drinks) => {
console.log(drinks);
return makeDrinks("美式咖啡");
})
.then((drinks) => {
console.log(drinks);
});
//這是你點的珍珠奶茶
//這是你點的英式紅茶
//這是你點的美式咖啡
假設店家今天的招牌ironman冬瓜檸檬賣完了,店員便會取消訂單,在程式碼上增加了 reject 函式,如果有客人點了這個品項就會執行,Promise轉為rejected狀態,並執行 catch 流程
function makeDrinks(drinksName) {
return new Promise((resolve, reject) => {
if (drinksName.includes("ironman")) {
reject("ironman冬瓜檸檬賣完了");
}
setTimeout(() => {
resolve(`這是你點的${drinksName}`);
}, 2000);
});
}
makeDrinks("美式咖啡")
.then((drinks) => {
console.log(drinks);
return makeDrinks("珍珠奶茶");
})
.then((drinks) => {
console.log(drinks);
return makeDrinks("ironman冬瓜檸檬");
})
.then((drinks) => {
console.log(drinks);
})
.catch((err) => {
console.log(err);
});
//這是你點的美式咖啡
//這是你點的珍珠奶茶
//ironman冬瓜檸檬賣完了
經過這次寫文章學習,對於 Promise 的理解大約從 1.5% 提升到 55% 左右,期許之後理解程度可以再提升至 87%
如果有任何錯誤的地方也請高手們指教了,感謝~