前言
前幾天講的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 萬的存款,他就會去找工作。
| 12
 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 裝的東西就是所有的結果。
只要有一個失敗,就直接失敗,就像是只要有一個前提條件沒達成,小白就沒辦法去找工作。
| 12
 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:失敗的訊息}
 | 
繼續上方的例子,小白做好準備要出發去找工作,他的策略是履歷海,什麼都投,投完後開心地坐在家中等消息。
| 12
 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的物件裡面,把失敗的訊息都放進去。
小白出發前往面試,他只要有上就好,成功了就不會繼續下一間。
| 12
 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);
 
 | 
假如完全都沒有任何公司是面試成功的話:
| 12
 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有結果,就回傳跟結束。
剛剛提到小白找到了工作,他很開心想要慶祝,所以打算去吃一間豪華的餐廳,他還沒想要要吃什麼,抱著不想找太久的心手舞足蹈的前往。
| 12
 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幾乎一模一樣,有了一個成功,其他都就不會去看直接結束。
但是要是第一間要去的不是牛排店,而是人很多的燒賣店呢?讓我們看下去。
| 12
 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成功後的訊息。
| 12
 3
 4
 5
 
 | const promise = Promise.resolve(1);
 promise.then((value) => {
 console.log(value);
 });
 
 | 
Promise.reject()
而reject就是Promise失敗後的訊息,所以要用 catch()去抓。
| 12
 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()