Promise.allSettled 폴리필 구현

문제 상황

여러 API를 동시에 호출하고 일부가 실패해도 성공한 데이터는 화면에 표시해야 했다. Promise.all은 하나라도 reject되면 catch로 빠져서 성공한 결과들도 받을 수 없었다.

Promise.all([api1(), api2(), api3()])
  .then(results => {
    // api2가 실패하면 여기 도달 불가
  })
  .catch(error => {
    // api1, api3 성공 결과를 받을 방법이 없음
  });

해결 방법

각 Promise를 catch로 감싸서 항상 fulfilled 상태로 만들었다.

function allSettled(promises) {
  return Promise.all(
    promises.map(promise =>
      promise
        .then(value => ({ status: 'fulfilled', value }))
        .catch(reason => ({ status: 'rejected', reason }))
    )
  );
}

// 사용
allSettled([api1(), api2(), api3()])
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log('성공:', result.value);
      } else {
        console.log('실패:', result.reason);
      }
    });
  });

추가 고려사항

  • Promise가 아닌 값이 들어올 수 있어서 Promise.resolve()로 감쌌다
  • ES2020에서 Promise.allSettled가 표준으로 추가된다고 한다
  • 당장은 이 패턴으로 충분히 동작했다

배치 작업이나 여러 독립적인 요청을 처리할 때 유용한 패턴이다.

Promise.allSettled 폴리필 구현