최종 코드는 맨 밑에 '덧2' 참고!
조건에 따라 api를 각각 따로 호출하고, 결과값은 합쳐서 state에 저장해야 하는 상황이다. 간단한 문제일 줄 알았는데 .then() 안에 있는 결과값을 어떻게 밖으로 빼고 가공해야 몰라서 한참 헤맸다.
if (조건문1) {
  fetch
    .get('uri')
    .then((res1) => res1)  // type : arr
    .catch(() => {})
}
if (조건문2) {
  fetch
    .get('uri')
    .then((res2) => res2)  // type : arr
    .catch(() => {})
}
// 원하는 결과값
setResult([...res1, ...res2]) // 대충 느낌만 반영한 코드
Promise.all() 함수를 통해 single promise로 만들고, 이를 .then()으로 받으면 2차원 array로 쓸 수 있게 된다.[].concat.apply([], exampleArr) 함수를 사용해서 1차원 배열로 만든다!let aPromise;
let bPromise;
   if (조건문1) {
      aPromise = fetch
                  .get('uri')
                  .then((res1) => res1)
                  .catch(() => {})
   }
   if (조건문2) {
       bPromise = fetch
                   .get('uri')
                   .then((res2) => res2)
                   .catch(() => {});
   }
// .filter() :api 반환값이 null일 경우, promise가 undefined이기 때문에 걸러주어야 한다
return [aPromise, bPromise].filter((promise) => promise); 
})
  .then((promises) => {
     Promise.all(promises)
       .then((twoDimenArr) => {
              setResult([].concat.apply([], twoDimenArr));
            });
          }
        })
더 간단한 방법이 있을 것 같지만 현재로선 이것이 최선이었습니다...🤗
어쨌든 해결!✨
흐름은 그대로 쓰고, 코드만 리펙토링 해보았다. 불필요한 .then()이 한 번 줄었다.
let aPromise;
let bPromise;
   if (조건문1) {
      aPromise = fetch
                  .get('uri')
                  .then((res1) => res1)
                  .catch(() => {})
   }
   if (조건문2) {
       bPromise = fetch
                   .get('uri')
                   .then((res2) => res2)
                   .catch(() => {});
   }
return Promise.all([aPromise, bPromise].filter((promise) => promise));
})
  .then((twoDepthArr) => {
       setResult([].concat.apply([], twoDepthArr));
  })
데이터가 null일 때 만들어지는 promise는 위 코드처럼 filter로 걸러낼 수 없다!
Be Careful with Async Functions that Return Booleans
a Promise object is not one of the eight falsy values in JavaScript, so checking its truthiness is pointless: When coerced to a boolean, a Promise is always true.
promise는 false로 치지 않는 타입이므로, 강제로 체크할 경우 무조건 true로 확인된다는 뜻.
그러므로, 데이터가 null로 올 경우를 거르고 싶다면 two depth array로 변환된 다음에 걸러야 유효하다.
let aPromise;
let bPromise;
   if (조건문1) {
      aPromise = fetch
                  .get('uri')
                  .then((res1) => res1)
                  .catch(() => {})
   }
   if (조건문2) {
       bPromise = fetch
                   .get('uri')
                   .then((res2) => res2)
                   .catch(() => {});
   }
return Promise.all([aPromise, bPromise]);
})
  .then((twoDepthArr) => {
     // 방어 코드
     const filterArr = twoDepthArr.filter((item) => Boolean(item));
     setResult([].concat.apply([], filterArr));
  })
Promise.allSettled([promise1, promise2, ...])를 사용해보세요.
allSettled는 { status, value 또는 reason }을 리턴하는데요. promise가 resolve될 경우 value, reject 될 경우 reason이 됩니다. status는 fulfilled 또는 rejected가 되구요. allSettled를 사용하면 프라미스가 실패할 경우를 조치해줄 수 있어서 편리해요.
그리고 프라미스를 다룰때 많이 쓰이는게 async 함수인데요. 함수를 만들때 async 키워드를 사용하여 비동기 함수로 만들고, 내부에서 await을 이용해서 결과값을 동기적으로 처리할 수 있어요.
아래 간단한 예시를 적어봤어요.
function async combinePromise (promise1, promise2) {
// promise들의 결과를 result에 담고, result를 순회하며 value에 담겨있는 객체(보통 api 결과는 객체형태일 것으로 예상)를 합쳐준다.
const result = await Promise.allSettled([promise1(), promise2()])
return result.reduce((a,b) => ({ ...a.value, ...b.value }))
}
열공하세요! 화이팅~! 💪