Promise API

100pearlcent·2021년 11월 15일
0

JavaScript

목록 보기
22/22
post-thumbnail

Promise 클래스는 5가지 정적 메서드를 가지고 있다

Promise.all ⭐

  • 프라미스가 하나라도 거절되면 전체를 거절한다

여러 개의 프라미스를 동시에 실행시키고 모든 프라미스가 준비될 때까지 기다린다고 가정할 때
복수의 URL에 동시에 요청을 보내고 다운로드가 모두 완료된 후에 콘텐츠를 처리할 때 이런 상황이 발생한다

let promise = Promise.all([...promises...]);

Promise.all은 요소 전체가 프라미스인 배열(iterable 객체)을 받고 새로운 프라미스를 반환한다

배열 안 프라미스가 모두 처리되면 새로운 프라미스가 이행되는데, 배열 안 프라미스의 결괏값을 담은 배열이 새로운 프라미스의 result가 된다


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);

Promise.all은 3초 후에 처리되고, 반환되는 프라미스의 result는 배열 [1, 2, 3]이 된다

배열 result의 요소 순서는 Promise.all에 전달되는 프라미스 순서와 상응한다
Promise.all의 첫 번째 프라미스는 가장 늦게 이행되더라도 처리 결과는 배열의 첫 번째 요소에 저장된다

let urls = [
  'https://api.github.com/users/jinju',
  'https://api.github.com/users/baek',
  'https://api.github.com/users/pearl'
];

// fetch를 사용해 url을 프라미스로 매핑
let requests = urls.map(url => fetch(url));

// Promise.all은 모든 작업이 이행될 때까지 기다림
Promise.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));

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이 반환하는 프라미스는 에러와 함께 바로 거부된다

2초 후 두 번째 프라미스가 거부되면서 Promise.all 전체가 거부되고, .catch가 실행된다
거부 에러는 Promise.all 전체의 결과가 된다


- ⚠️ 에러가 발생하면 다른 프라미스는 무시된다

프라미스가 하나라도 거부되면 Promise.all은 즉시 거부되고 배열에 저장된 다른 프라미스의 결과는 사라져버리고 이행된 프라미스의 결과도 무시된다
fetch를 사용해 호출 여러 개를 만들면, 그 중 하나가 실패하더라도 호출은 계속 일어난다
그렇더라도 Promise.all은 다른 호출을 더는 신경쓰지 않는다
프라미스가 처리되긴 하나 그 결과는 무시된다

프라미스에는 취소 개념이 없어서 Promise.all도 프라미스를 취소하지 않습니다
AbortController를 사용하면 프라미스 취소가 가능하긴 하지만 프라미스 API는 아니다


- iterable 객체가 아닌 값도 넘길 수 있다

Promise.all(...)은 대개 프라미스가 요소인 iterable 객체(대부분 배열)를 받는다
그런데 프라미스가 아닌 객체가 배열을 구성하면, 요소가 그래도 결과 배열로 전달된다

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

그래서 이미 결과를 알고 있는 값은 Promise.all로 그냥 전달하면 된다



Promise.allSettled

구식 브라우저는 폴리필이 필요하다

프라미스가 하나라도 거절되면 전체를 거절하는 Promise.all에 반해 Promise.allSettled는 모든 프라미스가 처리될 때 까지 기다린다
반환되는 배열은 다음과 같은 요소를 가진다

  • 응답 성공 시 : {status: "fulfilled", value: result}
  • 에러 발생 시 : {status: "rejected", reason: error}

let urls = [
  'https://api.github.com/users/jinju',
  'https://api.github.com/users/baek',
  '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}`);
      }
    });
  });

fetch를 사용해 여러 사람의 정보를 가져올 때 여러 요청 중 하나가 실패해도 다른 요청 결과는 여전히 있어야 할 때 Promise.allSettled가 사용된다


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

Promise.allSettled를 사용하면 위 처럼 각 프라미스의 상태와 값 또는 에러를 받을 수 있다



Promise.race

Promise.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

첫 번 째 프라미스가 가장 빨리 처리상태가 되기 때문에 첫 번째 프라미스의 결과가 result값이 된다



Promise.resolve/reject

프라미스 메서드 Promise.resolvePromise.rejectasync/await이 생긴 이후로 쓸모 없어졌기 때문에 잘 사용되지 않는다



요약

Promise클래스에는 5가지 정적 메서드가 있다

  1. Promise.all(promises) : 모든 프라미스가 이행될 때 까지 기다렸다가 그 결괏값을 담은 배열을 반환한다. 주어진 프라미스 중 하나라도 실패하면 Promise.all은 거부되고, 나머지 프라미스의 결과는 무시된다
  2. Promise.allSettled(promises) : 최근에 추가된 메서드로 모든 프라미스가 처리될 때 까지 기다렸다가 그 결과(객체)를 담은 배열을 반환한다
  • status : "fulfilled" 또는 "rejected"
  • value 또는 reason
  1. Promise.race(promises) : 가장 먼저 처리된 프라미스의 결과 또는 에러를 담은 프라미스를 반환한다
  2. Promise.resolve(value) : 주어진 값을 사용해 이행 상태의 프라미스를 만든다
  3. Promise.reject(error) : 주어진 에러를 사용해 거부 상태의 프라미스를 만든다


0개의 댓글