實作 Promise methods
什麼是 Promise
A Promise is an object representing the eventual completion or failure of an asynchronous operation Promise 是一個表示非同步運算的最終完成或失敗的物件
如何創建 Promise
使用 new
關鍵字創建,接受一個函式為參數,這個函式又稱為 executor,executor 會立即執行。executor 函式,會再接受另外兩個函式參數: resolve 成功調用的函式、reject 失敗時調用的函式
new Promise((resolve, reject) => {
console.log("executor 立即執行"); // executor 立即執行
});
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url === "www.google.com") {
resolve("hello google");
} else {
reject("it is not google");
}
}, 3000);
});
}
// 請求成功
requestData("www.google.com").then((res) => {
console.log(res); //hello google
});
// 請求失敗
requestData("www.yahoo.com").catch((e) => console.log(e)); //it is not google
Promise 的狀態
一個 Promise 一定會處於以下三種狀態的其中一種
pending
:初始狀態,執行了 executor,但還在等待中。fulfilled
:表示操作完成,執行 resolve 函式。rejected
:表示操作失敗,執行 reject 函式。
Promise 方法
Promise.all()
: 當所有 Promises 都成功時,回傳包含所有 Promise resolve 的陣列; 如果任何一個 Promise 被拒絕,立刻回傳 reject 的 PromisePromise.race()
: 回傳第一個 resolve/reject 的 Promise。即使其他 Promise 未完成,只要有一個完成,就會立刻回傳 resolve/reject 的結果Promise.any()
: 回傳第一個 resolve 的 Promise。倘若所有 Promise 都失敗,則回傳 reject 的 PromisePromise.allSettled()
: 所有 Promise 都完成後,回傳包含所有結果(resolve/reject)的 Promise 陣列
實作 Promise.all()
- 接受多個 Promise 物件的 Iterable,例如:Array、Map、Set
- 如果 Iterable 為空,則 fulfilled 值為空陣列
- 如果 Iterable 不為空,則:
- 所有 promises 都 fulfilled ⇒ 依序回傳 fulfilled 的值
- 有任一個 promise 被 rejected ⇒ 立刻回傳 reject
- 若不是 Promise 物件,則自動使用
Promise.resolve
方法來轉換
function promiseAll(promises) {
// 判斷輸入是否為 Iterable
const isIterable =
((typeof promises === "object" && promises !== null) ||
typeof promises === "string") &&
typeof promises[Symbol.iterator] === "function";
// 不是的話就回傳錯誤訊息
if (!isIterable) {
return new TypeError("Arguments must be iterable");
}
// 把 Iterable 轉成 Array
promises = Array.from(promises);
// 如果輸入是空的,就 resolve 一個空陣列
if (!promises.length) {
return Promise.resolve([]);
}
// 先宣告一個最終要 resolve 的 outputs,
// 之後每個 promise 被 fulfilled 時,就放到 outputs 裡面
const outputs = [];
// 紀錄有多少個 promise 已經 fulfilled
let resolveCounter = 0;
// Promise.all() 最終要回傳一個 promise
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
//考量p可能不一定是promise,也可能是常數
Promise.resolve(p)
.then((value) => {
// 當輸入的每個 promise 成功 fulfilled 時,就放到 outputs
// 透過 index,我們可以確保順序正確
outputs[index] = value;
// 每次成功放入 outputs 時,counter 要加一
resolveCounter += 1;
// 當 counter 等於 promises 長度時,代表所有的 promise 都 fulfilled
// 這時最外面的 promise 就可以 resolve
if (resolveCounter === promises.length) {
resolve(outputs);
}
})
.catch((e) => {
// 只要有一個被 reject 就馬上 reject
reject(e);
});
});
});
}
實作 Promise.race()
- 接受多個 promises 的 Iterable,例如:Array、Map、Set
- 回傳最先 fulfill 或最先被 reject 的那個 Promise 值
- 如果 Iterable 為空,則回傳的 promise 物件為 pending
function promiseRace(promises) {
// 判斷輸入是否為 Iterable
const isIterable =
((typeof promises === "object" && promises !== null) ||
typeof promises === "string") &&
typeof promises[Symbol.iterator] === "function";
// 不是的話就回傳錯誤訊息
if (!isIterable) {
return new TypeError("Arguments must be iterable");
}
return new Promise((resolve, reject) => {
promises.forEach((p) => {
Promise.resolve(p)
.then((val) => {
// 只要有 fulfill 的,就馬上 resolve
resolve(val);
})
.catch((e) => {
// 或是只要有 reject 的,就馬上 reject
reject(e);
});
});
});
}