Promise.allSettled 폴리필 구현하기
문제 상황
배치 작업에서 여러 외부 API를 호출한 뒤, 성공/실패 여부를 각각 로깅해야 했다. Promise.all을 사용하면 하나라도 실패할 경우 catch로 빠져버려서 나머지 결과를 확인할 수 없었다.
// 기존 코드 - 하나라도 실패하면 전체 실패
Promise.all([
fetchUser(1),
fetchUser(2),
fetchUser(3)
])
.then(results => console.log(results))
.catch(err => console.error(err)); // 여기로 빠짐
해결 방법
Promise.allSettled가 ES2020에 제안되어 있지만, 현재 브라우저에서는 지원하지 않는다. 직접 구현했다.
function allSettled(promises) {
return Promise.all(
promises.map(promise =>
Promise.resolve(promise)
.then(value => ({ status: 'fulfilled', value }))
.catch(reason => ({ status: 'rejected', reason }))
)
);
}
각 Promise를 try-catch로 감싸서 무조건 fulfilled 상태로 만드는 방식이다. 결과 객체에 status와 value/reason을 담아 반환한다.
사용 예시
allSettled([
fetchUser(1),
fetchUser(2),
fetchUser(999) // 존재하지 않는 유저
]).then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
logger.info(`User ${index}: ${result.value.name}`);
} else {
logger.error(`User ${index}: ${result.reason.message}`);
}
});
});
모든 결과를 받아서 개별적으로 처리할 수 있게 되었다. 배치 작업에서 일부 실패가 전체 프로세스를 멈추지 않도록 개선되었다.