Promise.allSettled vs Promise.all, 에러 처리가 다르다
문제
대시보드를 만드는데 여러 API를 동시에 호출해야 했다. Promise.all을 썼더니 하나만 실패해도 전체가 reject 되면서 성공한 데이터까지 날아가버렸다.
// 하나라도 실패하면 전부 날아감
try {
const [users, orders, stats] = await Promise.all([
fetchUsers(),
fetchOrders(), // 이게 실패하면
fetchStats(),
]);
} catch (err) {
// users, stats 결과도 못 쓴다
}
해결
Promise.allSettled를 쓰면 전부 완료될 때까지 기다리고, 각각의 성공/실패를 따로 확인할 수 있다.
const results = await Promise.allSettled([
fetchUsers(),
fetchOrders(),
fetchStats(),
]);
// 각 결과의 status로 성공/실패 판별
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`API ${index} 성공:`, result.value);
} else {
console.log(`API ${index} 실패:`, result.reason);
}
});
실무에서는 이런 식으로 패턴화해서 쓴다:
const [usersResult, ordersResult, statsResult] = await Promise.allSettled([
fetchUsers(),
fetchOrders(),
fetchStats(),
]);
const dashboard = {
users: usersResult.status === 'fulfilled' ? usersResult.value : [],
orders: ordersResult.status === 'fulfilled' ? ordersResult.value : [],
stats: statsResult.status === 'fulfilled' ? statsResult.value : null,
};
// 실패한 것만 로깅
const failures = [usersResult, ordersResult, statsResult]
.filter(r => r.status === 'rejected');
if (failures.length > 0) {
console.error('일부 API 실패:', failures.map(f => f.reason));
}
핵심 포인트
Promise.all은 하나라도 실패하면 즉시 reject — 전부 성공해야만 하는 경우에 쓴다Promise.allSettled는 전부 완료 후 각각 결과를 줌 — 부분 실패를 허용할 때 쓴다- 대시보드, 배치 처리처럼 “가능한 건 보여주고, 실패한 건 따로 처리”하는 상황에 딱이다