티스토리 뷰

11.5 Promise API

Promise.all

여러 개의 URL에 동시에 요청을 보내고, 모두 완료된 후 콘텐츠를 처리하고 싶을 때 Promise.all을 사용할 수 있다.

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert); // 프라미스 전체가 처리되면 1, 2, 3이 반환됩니다. 각 프라미스는 배열을 구성하는 요소가 됩니다.

만약 Promise.all로 전달되는 프라미스 중 하나라도 거부되면, Promise.all 전체가 거부되고. catch가 실행된다. 즉 다른 프라미스 결과는 모두 무시된다. 

Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 발생!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).catch(alert); // Error: 에러 발생!

이터러블 객체가 아니어도 Promise.all의 파라미터로 넘길 수 있다.

Promise.all([
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000)
  }),
  2,
  3
]).then(alert); // 1, 2, 3

Promise.allSettled

Promise.allSettled는 모든 프라미스가 다 처리될 때까지 기다리고, 실패한 프라미스도 포함하여 각 상태와 값을 받을 수 있다.

let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/Violet-Bora-Lee',
  'https://no-such-url'
];

Promise.allSettled(urls.map(url => fetch(url)))
  .then(results => { // (*)
    results.forEach((result, num) => {
      if (result.status == "fulfilled") {
        alert(`${urls[num]}: ${result.value.status}`);
      }
      if (result.status == "rejected") {
        alert(`${urls[num]}: ${result.reason}`);
      }
    });
  });

// ----------------

[
  {status: 'fulfilled', value: ...응답...},
  {status: 'fulfilled', value: ...응답...},
  {status: 'rejected', reason: ...에러 객체...}
]

위 API는 비교적 최근에 추가된 스펙이라 폴리필로 추가해야 할 수도 있다.

Promise.race

말 그대로 race이다. all과 비슷하게 여러 프라미스를 받아서 처리하는데, 가장 먼저 처리되는 결과만 반환한다.

let promise = Promise.race(iterable);

// ----------

Promise.race([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 발생!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1

Promise.resolve와 Promise.reject

Promise.resolve와 Promise.reject는 async/await에 의해 거의 사용되지 않는다. 예시만 살펴보자.

// 함수가 프라미스를 반환하도록 해야할 때 사용할 수 있음.
// 반환값이 항상 프라미스가 되게 한다.
let cache = new Map();

function loadCached(url) {
  if (cache.has(url)) {
    return Promise.resolve(cache.get(url)); // (*)
  }

  return fetch(url)
    .then(response => response.text())
    .then(text => {
      cache.set(url,text);
      return text;
    });
}

// ---------

let promise = new Promise((resolve, reject) => reject(error));

reject는 거의 사용되지 않는다. 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday