Promise 的好用之處在於,可以確保事件完成後再執行後面的行為,也解決了傳統 callback 波動拳的問題。它用 resolve, reject 來傳遞函式執行後為成功或是失敗的訊息,再用 then 與 catch 來做對應處理。這一篇就用範例快速了解一下 Promise 怎麼用吧!
情境舉例:
當我要去旅遊,首先必須先整理行李後才能出發,
因此行李整理完成,我才會叫車
Promise 基礎範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function checkLuggage() { return new Promise((resolve, reject) => { if (parseInt(Math.random() * 2)) { setTimeout(resolve, 10000 * Math.random(), '收好行李'); } else { reject('想慢慢收') } }) } checkLuggage().then((data)=> { console.log(data, '可以叫車了!'); }).catch((err)=> { console.log(err, '先不要叫車') });
|
迴圈與 Promise, Promise.all 的運用
Promise.all() 這個方法可以同時執行很多 Promise,並在全部都執行完後回傳。
情境舉例:
繼續上一個情境,整理行李要拿的東西實在太多
假設我只要發送指令,就可以讓機器人自動去幫我做拿好(做夢
那整理行李這件事,我就可以個別發送『拿衣服』、『拿褲子』、『拿襪子』指令,讓他們去拿 XD
當我發送出指令的時候,我總要知道他們哪時候完成,才方便我打電話叫車嘛~
此時就可以用 promise.all 來確定事情完成:
先制定好去拿的這個事件,並在完成拿取時回報完成
1 2 3 4 5 6
| let todos = ['拿衣服', '拿褲子', '拿襪子']; function getThing(todo) { return new Promise((resolve, reject) => { setTimeout(resolve, 10000 * Math.random(), todo+'完成'); }) }
|
接著用 checkLuggage 來統一發送與接受完成的回傳:
1 2 3 4 5 6 7 8 9 10 11 12
| function checkLuggage() { return new Promise((resolve, reject) => { let allTodo = []; todos.forEach(todo => { allTodo.push(getThing(todo)); }) Promise.all(allTodo).then((results) => { const msg = '全部完成:'+ results; resolve(msg); }) }); }
|
最後執行 checkLuggage 函式,等到全部事情都完成了才會執行 callForCar 函式
1 2 3 4 5 6 7
| function callForCar() { console.log('叫車') } checkLuggage().then(data => { console.log(data) callForCar(); });
|
這個方法常使用在不確定陣列中(如同範例的 todos)有多少個項目,直接透過迴圈的方式紀錄所有 promise 事件。當其中一個為失敗的話,也可以使用 catch 來做取得錯誤後的處理。這部分就和一開始的 Promise 基礎範例是一樣的道理~
小結
透過 Promise 就可以確保事件完成後才觸發後面要執行的事項。
就不會發生行李還沒整理好,車子就來了的情形啦!