前幾天講的Promise
的then()、catch()、finally()也是Promise
的methods,從MDN的定義上會把這三種methods稱之為Instance methods
,而今天要講的是Static methods
,中文叫做靜態方法,大致上可以分成六種,這些的方法都是為了更好的使用Promise
而被發明出來,可能用不到但懂了沒壞處。
哪六種:
會嘗試用好理解的方式介紹,let's go。
執行很多的Promise
會用到,簡單來說,全部都達成才會成功,不然就會失敗。
舉一個例子,小白願意去找工作,但他有著前提條件,只要他擁有了一台車,然後有了房子,還擁有100萬的存款,他就會去找工作。
Promise.all([
new Promise((resolve) => setTimeout(() => resolve("獲得車"), 100)),
new Promise((resolve) => setTimeout(() => resolve("獲得房子"), 200)),
new Promise((resolve) => setTimeout(() => resolve("獲得100萬"), 300)),
new Promise((resolve) => setTimeout(() => resolve("=> 好! 去工作"), 400)),
]).then(console.log);
// [ '獲得車', '獲得房子', '獲得100萬', '=> 好! 去工作' ]
會等到全部的結果都成功,才會全部都 resolve
, 會發現說它回傳的會是一個array,這個array裝的東西就是所有的結果。
只要有一個失敗,就直接失敗,就像是只要有一個前提條件沒達成,小白就沒辦法去找工作。
Promise.all([
new Promise((resolve) => setTimeout(() => resolve("獲得車"), 100)),
new Promise((resolve) => setTimeout(() => resolve("獲得房子"), 200)),
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("沒有一百萬,沒人要給你")), 300)
),
new Promise((resolve) => setTimeout(() => resolve("=> 好! 去工作"), 400)),
])
.then(console.log)
.catch(console.log);
// Error: 沒有一百萬,沒人要給你
其中有一個被reject
就會導致全部整個Promise.all
都被reject
,最後的結果就是reject
裡面寫好的Error
訊息。
情境是使用在都每種Promise
都想知道結果的時候。
代表說成功或是失敗的結果都會被記錄下來,這兩種都會被裝在一個陣列裡面。
成功:
{status:"fulfilled", value:成功的訊息}
失敗:
{status:"rejected", reason:失敗的訊息}
繼續上方的例子,小白做好準備要出發去找工作,他的策略是履歷海,什麼都投,投完後開心地坐在家中等消息。
Promise.allSettled([
// 找工作是一個包著promise的函式,裡面就會放失敗跟成功的訊息
找工作("第一間公司", 100),
找工作("第二間公司", 200),
找工作("第三間公司", 300),
])
.then((value) => console.log(value));
.catch((err) => console.log(err));
// 結果=>
[
{ status: 'fulfilled', value: '第一間公司:發來面試請求!' },
{ status: 'rejected', reason: '第二間公司,無聲卡' },
{ status: 'fulfilled', value: '第三間公司:發來面試請求!' },
]
其中有一個被reject
,也會把其他結果通通跑完,跑完之後會能看到所有的結果,無論結果是如何,都會全部都被settle
,所以叫做allSettled
。
假如成功就馬上成功,直到全部都失敗。
而在全部都失敗的狀態下,會回傳一個叫做AggregateError
的物件裡面,把失敗的訊息都放進去。
小白出發前往面試,他只要有上就好,成功了就不會繼續下一間。
Promise.any([
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("失敗,下一間")), 100)
),
new Promise((resolve, reject) =>
setTimeout(() => resolve("成功找到工作"), 200)
),
new Promise((resolve, reject) => setTimeout(() => resolve("回家睡覺"), 300)),
]).then(console.log); // 成功找到工作
假如完全都沒有任何公司是面試成功的話:
Promise.any([
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("失敗,下一間")), 100)
),
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("失敗,下一間")), 200)
),
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("失敗,下一間")), 300)
),
])
.then(console.log)
.catch((error) => {
console.log(error.constructor.name, error.errors);
});
// 會出現:
AggregateError [
Error: 失敗,下一間
Error: 失敗,下一間
Error: 失敗,下一間
]
跟Promise.any
有點像,當一個promise
有結果,就回傳跟結束。
剛剛提到小白找到了工作,他很開心想要慶祝,所以打算去吃一間豪華的餐廳,他還沒想要要吃什麼,抱著不想找太久的心手舞足蹈的前往。
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve("吃牛排"), 200)),
new Promise((resolve, reject) => setTimeout(() => resolve("吃拉麵"), 300)),
new Promise((resolve, reject) => setTimeout(() => resolve("吃火鍋"), 400)),
])
.then(console.log)
.catch((error) => {
console.log(error);
});
// 吃牛排
小白看到了牛排,然後裡面就有位子不用排隊,二話不說就直接開吃了。
到這邊跟Promise.any
幾乎一模一樣,有了一個成功,其他都就不會去看直接結束。
但是要是第一間要去的不是牛排店,而是人很多的燒賣店呢?讓我們看下去。
Promise.race([
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("人太多,不吃了")), 100)
),
new Promise((resolve, reject) => setTimeout(() => resolve("吃牛排"), 200)),
new Promise((resolve, reject) => setTimeout(() => resolve("吃拉麵"), 300)),
new Promise((resolve, reject) => setTimeout(() => resolve("吃火鍋"), 400)),
])
.then(console.log)
.catch((error) => {
console.log(error);
});
// Error: 人太多,不吃了
小白第一間到了燒賣店,看到了那人山人海的群眾,內心湧入一陣倒胃,突然就沒有吃飯的慾望了,於是就直接回家結束了這回合。
這就是Promise.race
的特性,不管是成功還是失敗,Promise.race
都會被解決。
來複習一下這兩者的差別:
Promise.race:
不管是成功還是失敗,都會直接完成。
Promise.any:
當成功了,或是全部都失敗,才會完成。
兩個都會有拒絕的狀況,Promise.race
的拒絕狀況是因為碰到了第一個Promise
拒絕後就馬上拒絕,而Promise.any
是全部都被拒絕後,回傳一個,AggregateError
。
要如何使用它們兩個,要依照情境而定,可以知道的是他們兩個很相似但是依舊是不同的東西。
我的理解是設定Promise
成功後的訊息。
const promise = Promise.resolve(1);
promise.then((value) => {
console.log(value);
}); //1
而reject
就是Promise
失敗後的訊息,所以要用catch()去抓。
const promise = Promise.reject(1);
promise.catch((value) => {
console.log(value);
});
每一種方法都有它適合的情境,在使用promise
可以試著用用看這些方法~說不定會發現方便又好用,而我個人體感跟爬文看到來說,Promise.all
這個方法是實際上會使用最多的,所以可以考慮先從這個開始下手認識,那麼今天就是這些,謝謝明天見。
[1] MDN - Promise
[2] What is the difference between Promise.any() and Promise.race()