Promise 객체는 5가지의 정적 메서드를 가지고 있다.

1. Promise.resolve & Promise.reject

Promise.resolve와 Promise.reject는 전달받은 값을 래핑하여 Promise를 생성한다. Promise.resolve는 전달받은 값을 resolve하는 Promise를 생성한다.

const promise = Promise.resolve(100);
promise.then(console.log); // 100

이는 아래 코드와 동일하다.

const promise = new Promise((resolve) => resolve(100));
promise.then(console.log); // 100

Promise.reject는 전달받은 값을 reject하는 Promise를 생성한다.

const promise = Promise.reject(new Error('error'));
promise.catch(console.log); // Error: error

이는 아래 코드와 동일하다.

const promise = new Promise((resolve, reject) => reject(new Error('error')));
promise.catch(console.log); // Error: error

2. Promise.all

Promise.all은 여러 비동기 처리를 모두 병렬 처리한다.

Promise.all(iterable)

Promise.all은 Promise를 요소로 갖는 배열 등의 이터러블을 전달받는다. 전달받은 모든 Promise가 모두 fulfilled 상태가 되면, 모든 처리 결과를 배열에 저장해 새로운 Promise를 반환한다.

const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000));
const promise2 = new Promise(resolve => setTimeout(() => resolve(3), 3000));
const promise3 = new Promise(resolve => setTimeout(() => resolve(5), 1000));

// 병렬 처리 (약 5초 소요됨)
const resultPromise = Promise.all([promise1, promise2, promise3]);
resultPromise.then(console.log); // [1, 3, 5]

Promise.all은 전달받은 배열의 Promise가 모두 fulfilled 상태가 되면 종료한다. 그러므로 Promise.all이 종료하는 데 소요되는 시간은, 가장 늦게 fulfilled 상태가 되는 Promise의 시간보다 약간 더 걸린다. 위 코드에서는 약 5초가 소요된다.

한편, Promise.all은 처리 순서를 보장한다. 전달받은 배열의 첫 번째 Promise가 마지막으로 fulfilled 되어도, 그 첫 번째 Promise의 resolve 결과부터 순서대로 배열에 저장한다.

그러나 만일, 전달받은 배열의 Promise 중 하나라도 rejected 상태가 되면, 그 즉시 처리를 종료하고 Promise를 반환한다.

const promise1 = new Promise((_, reject) => setTimeout(() => reject(new Error('one')), 5000));
const promise2 = new Promise((_, reject) => setTimeout(() => reject(new Error('two')), 3000));
const promise3 = new Promise((_, reject) => setTimeout(() => reject(new Error('three')), 1000));

const resultPromise = Promise.all([promise1, promise2, promise3]);
resultPromise.catch(console.log); // Error: three

위 코드에서 promise3이 가장 먼저 rejected 상태가 된다. Promise.all은 그 즉시 종료하고 Promise를 반환하며, promise3의 에러가 catch로 전달된다.

마지막으로, Promise.all에 전달된 이터러블의 요소가 Promise가 아닌 경우가 있다. 이 때, Promise.resolve를 사용하여 자동으로 Promise로 래핑한다.

const resultPromise = Promise.all(['a', 'b', 'c']);
resultPromise.then(console.log); // ['a', 'b', 'c']

3. Promise.race

Promise.race(iterable)

Promise.race도 Promise를 요소로 갖는 배열 등의 이터러블을 전달받는다. 가장 먼저 fulfilled가 된 Promise의 처리 결과를 resolve하는 새로운 Promise를 리턴한다.

const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000));
const promise2 = new Promise(resolve => setTimeout(() => resolve(3), 3000));
const promise3 = new Promise(resolve => setTimeout(() => resolve(5), 1000));

const resultPromise = Promise.race([promise1, promise2, promise3]);
resultPromise.then(console.log); // 5

가장 먼저 fulfilled가 된 것은 promise3이다. promise3의 resolve 처리 결과는 5이다. 따라서 Promise.race는 5를 resolve하는 새로운 Promise를 반환한다.

한편, 전달받은 배열의 Promise 중 하나라도 rejected 상태가 되면, 그 즉시 처리를 종료하고 Promise를 반환한다. 이는 Promise.all과 동일하다.

const promise1 = new Promise((_, reject) => setTimeout(() => reject(new Error('one')), 5000));
const promise2 = new Promise((_, reject) => setTimeout(() => reject(new Error('two')), 3000));
const promise3 = new Promise((_, reject) => setTimeout(() => reject(new Error('three')), 1000));

const resultPromise = Promise.race([promise1, promise2, promise3]);
resultPromise.catch(console.log); // Error: three

4. Promise.allSettled

Promise.allSettled(iterable)

Promise.allSettled는 Promise를 요소로 갖는 배열 등의 이터러블을 전달받는다. 전달된 Promise가 모두 settled 상태(fulfilled or rejected)가 되면 결과를 배열로 리턴한다.

const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 3000));
const promise2 = new Promise((_, reject) => setTimeout(() => reject(new Error('error')), 2000));

const resultPromise = Promise.allSettled([promise1, promise2]);
resultPromise.then(console.log);
/* 
[
  {status: 'fulfilled', value: 1},
  {status: 'rejected', reason: Error: error at <anonymous>:2:69}
] 
*/

Promise.allSettled가 리턴한 배열에는 fulfilled나 rejected 상태와는 관계없이 모든 Promise의 결과가 저장되어 있다.

참고자료

“모던 자바스크립트 Deep Dive”, 이웅모, 위키북스, 2020.09.25, pp.858-863

(정리한 글에서 틀린 것이 있다면 꼭 지적해 주세요. 감사히 배우겠습니다)