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