TL;DR


<aside> 💡 처리(settled) 상태는 이행(fulfilled) 또는 거절(rejected) 상태를 모두 포함한다.

</aside>

Promise.all


<aside> 💡 프로미스 후속 처리 메서드를 이용한 체이닝은 순차적 처리, Promise.all은 병렬(동시) 처리 차이점 기억. Promise.all은 마지막 이행(fulfilled) 상태가 된 프로미스의 처리 시간보다 조금 더 길다.

</aside>

기본 사용법

Promise.all 메서드는 여러 개의 비동기 처리를 병렬로 처리할 수 있다. 여러 개의 프로미스를 동시에 실행시키고, 모든 프로미스가 fulfilled(이행) 상태가 된 후 작업을 처리 해야할 때 사용한다.

Promise.all 메서드는 처리 순서를 보장하며, 전달받은 프로미스가 1개라도 rejected 상태가 되면 나머지 프로미스가 이행 상태가 되는 것을 기다리지 않고 즉시 종료하는 특징이 있다.

// Promise.all 기본 구문
const promise = Promise.all([promise1, promise2, ...])

// then 대신 Promise.all 앞에 await 키워드 붙여서 결과값을 results 변수에 저장
const results = await Promise.all([promise1, promise2, ...]) // [...]
const [ res1, res2 ] = await Promise.all([promise1, promise2, ...]) // [...]

Promise.all 메서드는 프로미스를 요소로 갖는 이터러블(배열, 문자열 등)을 인자로 받는다. 인자로 전달받은 이터러블의 요소가 프로미스가 아니면, 암묵적으로 Promise.resolve 메서드를 이용해 프로미스로 래핑한다.

Promise.all([
  1, // Promise.resolve(1) 와 동일
  2, // Promise.resolve(2) 와 동일
]).then(console.log); // [1, 2]

Promise.all은 인자로 전달받은 배열의 모든 프로미스가 fulfilled 상태가 되면 종료된다. 모든 프로미스가 fullfilled 상태가 되면 resolved된 처리 결과를 배열에 저장하여 새로운 프로미스를 반환한다. Promise.all은 처리 순서를 보장하는 특징이 있다. 즉, 처리 결과 배열은 항상 Promise.all 인자에 전달한 순서와 같다. 예를들어 첫번째 프로미스가 가장 늦게 fulfilled 됐어도 처리 결과 배열엔 항상 첫번째 요소에 위치한다.

Promise.all([
  new Promise((resolve) => setTimeout(() => resolve(1), 5000)), // 3번째 이행
  new Promise((resolve) => setTimeout(() => resolve(2), 3000)), // 2번째 이행
  new Promise((resolve) => setTimeout(() => resolve(3), 1000)), // 1번째 이행
]).then(console.log); // 모든 프로미스가 처리되면 [1, 2, 3] 출력

Promise.all이 인자로 받은 프로미스가 하나라도 rejected 상태가 되면 나머지 프로미스가 fulfilled 상태가 되는 것을 기다리지 않고 즉시 종료한다. 즉, 1개 프로미스가 거절되면 Promise.all 전체가 거절되고 이행된 프로미스 결과도 무시된다. 이때 가장 먼저 거절된 프로미스의 에러가 catch 메서드로 전달되며, Promise.all 전체의 결과가 된다.

Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 2")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)),
])
  .then(console.log) // 건너뜀
  .catch(console.error); // Error: 에러 2 (에러 발생했으므로 Promise.all 종료)
Promise.all([
  new Promise((_, reject) => setTimeout(() => reject(new Error('에러 1')), 5000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('에러 2')), 3000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('에러 3')), 1000)),
])
  .then(console.log) // 건너뜀
  .catch(console.error); // Error: 에러 3 (가장 먼저 에러가 발생한 프로미스)

활용 예시 ⭐️