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가 표준으로 추가된다고 한다 - 당장은 이 패턴으로 충분히 동작했다
배치 작업이나 여러 독립적인 요청을 처리할 때 유용한 패턴이다.