本系列文章經過重新編排和擴充,已出書為ECMAScript關鍵30天。原始文章因當時準備時程緊迫,多少有些許錯誤。為了避免造成讀者的困擾,以及配合書籍的內容規劃,將會陸續更新本系列文章。
本篇文章在 2021/11/8 已更新。
寫 ES5 時,只要需要寫到非同步請求,我們或多或少都有接觸到 promise 的寫法。但是因為在 Javascript 中還沒有實作,所以還要額外匯入支援的函式庫或模組,像是 jQuery
、BlueBird
等。
ES2015 中,Promise 終於被納入標準。一直到現在,Promise 已經成為實作非同步方法中的基本方式。在 Fetch API
、Service Worker
等,主要也是以 Promise 實現非同步行為。所以今天就來好好認識吧!
當建立Promise物件時,內部會有一個狀態機制,紀錄目前的執行狀況。主要的狀態有以下幾種-
pending
:執行傳入Promise物件的非同步操作,呈現「擱置中」的狀態。settled
:執行結束後,透過呼叫Promise內建的函式參數,呈現「已解決」的狀態。其中,執行結果的成功與否,可以再分成以下兩種狀態-
fulfilled
:表示執行結果正常,或是操作成功,呈現「已實現」的狀態。rejected
:表示執行結果在意料之外,或操作失敗,呈現「已拒絕」的狀態。看個基本例子。
// 一秒後隨機取數,如果是偶數就會該數字,如果不是就回QQ
const p = new Promise((resolve, reject) => {
setTimeout(() => {
const n = Math.floor(Math.random() * 100);
console.log(n);
if (n % 2 == 0) resolve(n);
else reject("QQ");
}, 1000);
}).catch((err) => {
console.error(err);
});
// 57
// catch: QQ
// finally done!
// ---or---
// 22
// finally done!
Promise.all(promises)
同時完成多個 Promise。如果任務結束,且都無意外錯誤,就會執行then()
;反之則執行catch()
處理錯誤。
const f1 = fetch("/a.json");
const f2 = fetch("/b.json");
Promise.all([f1, f2])
.then(([r1, r2]) => {
console.log("jsons:", r1, r2);
// jsons: {...} {...}
})
.catch((err) => {
console.error(err);
});
Promise.race(promises)
如同字面上意思,同時執行多個 Promise,只要最先完成 resolve 的,就會以這個 resolve 的結果執行 then()
。
const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 200, "p1");
});
const p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 300, "p2");
});
Promise.race([p1, p2]).then((result) => {
console.log(result); // p1
});