今天來分享一個之前同事問我的問題,因為我們工作上很常用到的是 fetch
或是 request
,這種需要多發 request
的情境,但發 request
有一個問題就是 request
發送有機會不成功,那這樣使用 Promise.all
就會跑到一半停止讓整個流程變得很難處理。所以就來說明我們應該怎麼解決這個問題。
Promise 失敗彈出 catch
首先我們先用 setTimeout
來製作一個需要等待 1 sec
,但是會發生 catch
的例子來模擬情境:
const wait = new Promise((resolve, reject) => { setTimeout(() => { reject('reject err'); }, 1000) }); function promiseAll(promises) { return Promise.all(promises).then(res => { console.log(`res: ${res}`); }).catch(err => { console.log(`err: ${err}`); }); }; const waitArray = []; waitArray.push(wait); waitArray.push(wait); promiseAll(waitArray);
從上面範例可以看到,我製作了一個叫做 wait
的 Promise function
,使用 waitArray
把它裝起來,放入 promiseAl
,這樣寫是希望想要得到執行兩次 wait function
的結果,那我們來執行一下:
clarence ~ $ node index.js err: reject err
很明顯我們原本希望可以執行兩次 wait function
,但是因為 catch
的關係 Promise.all
直接吐出 catch
中斷了第二個 wait function
。
解決 Promise 失敗被 catch 的問題
OK! 我們現在清楚我們要解決的問題了,那我們來把 wait function
包一層起來讓它不要噴出 catch
感覺就可以解決這個問題了。
一開始先處理單個,包完應該會如下:
const wait = new Promise((resolve, reject) => { setTimeout(() => { reject('reject err'); }, 1000) }) const catchPromise = wait.then(res => res).catch(err => err); catchPromise.then(res => { console.log(`res: ${res}`); }).catch(err => { console.log(`err: ${err}`); });
一樣我們來執行一下!
clarence ~ $ node index.js res: reject err
OK! 跟預期的依樣,我們讓他在執行 Promise
的時候不要彈到 catch
,剩下就是把它改成多個的情況。
解決 Promise.all 失敗被 catch 的問題
const wait = new Promise((resolve, reject) => { setTimeout(() => { reject('reject err'); }, 1000) }) const waitArray = []; waitArray.push(wait); waitArray.push(wait); const catchPromiseMap = (promises) => { return promises.map(promise => { return promise.then(res => res).catch(err => err); }); } const promiseArray = catchPromiseMap(waitArray); Promise.all(promiseArray).then(res => { console.log(`res: ${res}`); }).catch(err => { console.log(`err: ${err}`); });
來執行一下吧!
clarence ~ $ node index.js res: reject err,reject err
OK! 太棒了!成功拉 ~ 我們終於實現一個使用 Promise all
,但是不會因為 catch
抓到而失敗的方法了!
參考資料
《AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC》
第 12 屆 iT 邦幫忙鐵人賽 DevOps 組冠的《用 CDK 定 義 AWS 架構》
第 11 屆 iT 邦幫忙鐵人賽《LINE bot 好好玩 30 天玩轉 LINE API》
一個熱愛分享的雲端工程師!