TIL 38. 여러 개의 Promise 객체를 동시에 다룰 때

CHAEIN·2021년 7월 30일
0

JavaScript

목록 보기
30/31
post-thumbnail

여러개의 Promise 객체를 동시에 다뤄야할 때 유용하게 사용할 수 있는 메소드 들이 있다.

(1) .all() 메소드

all 메소드는 인자로 들어온 배열안 모든 Promise 객체가 pending 상태에서 fulfileed 상태가 될때까지 기다린다. 모든 promise 객체들이 fuilled 상태가 되면 all 메소드가 리턴했던 Promise 객체는 fulfilled 상태가 되고, 각 Promise 객체의 작업 성공 결과들로 이루어진 배열을 그 작업성공 결과로 갖게 된다. 따라서 Promise.all()은 작업이 서로 종속되어 있는 경우 하나라도 작업이 거부될 시 모든 작업을 즉시 거부시키고 싶을 때 사용한다.

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

Promise.all([p1, p2, p3]).then((values) => {
  console.log(values); // [3, 1337, "foo"]
});

만약 인자로 들어온 객체들 중 하나라도 rejected 상태가 되면 all 메소드가 리턴한 promise 객체는 rejected 상태가 되고 동일한 작업 실패 정보를 갖게 된다. 객체가 rejected 상태가 되는 경우를 대비하기 위해선 이전에 배웠던 것처럼 catch 메소드를 붙여주면 된다.

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1_delayed_resolution"), 1000);
});

var p2 = new Promise((resolve, reject) => {
  reject(new Error("p2_immediate_rejection"));
});

Promise.all([
  p1.catch((error) => {
    return error;
  }),
  p2.catch((error) => {
    return error;
  }),
]).then((values) => {
  console.log(values[0]); // "p1_delayed_resolution"
  console.error(values[1]); // "Error: p2_immediate_rejection"
});

(2) .allSetteled() 메소드

Promise.all()은 인자로 존재하는 Promise 객체 중 하나라도 rejected가 되면 리턴하는 Promise 객체도 rejected 상태가 되고 동일한 작업 실패 결과를 갖는 반면 Promise.allSetteled()는 인자로 주어진 객체 배열의 Promise 객체가 모두 작업이 완료되면 각각의 작업 결과를 리턴한다. 따라서 성공적으로 완료하기 위해 서로 의존하지 않는 여러 비동기 작업이 있거나 항상 각 Promise 의 작업 결과를 알고 싶을 때 사용한다.

Promise.allSettled([
  Promise.resolve(33),
  new Promise((resolve) => setTimeout(() => resolve(66), 0)),
  99,
  Promise.reject(new Error("an error")),
]).then((values) => console.log(values));

// [
//   {status: "fulfilled", value: 33},
//   {status: "fulfilled", value: 66},
//   {status: "fulfilled", value: 99},
//   {status: "rejected",  reason: Error: an error}
// ]

fulfilled 상태와 rejected 상태를 묶어서 settled 상태라고 하는데 allSettled 메소드는 말 그대로 배열 속 Promise 객체들이 settled 상태가 되기만 하면 된다. 이에 반해 위에서 배운 all 메소드는 모든 Promise 객체들이 fulfilled 상태가 되기를 기다리는 작업이다.

(3) .race() 메소드

race 메소드도 all 메소드처럼 여러 Promise 객체들이 있는 배열을 아규먼트로 받지만 가장 먼저 fulfilled 또는 rejected 상태가 된 Promise 객체와 동일한 상태의 결과를 갖게 된다는 점에서 다르다.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "one");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "two");
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

(4) .any() 메소드

any 메소드는 인자로 받은 여러 Promise 객체들 중에서 가장 먼저 fulfilled 상태가 된 Promise 객체의 상태와 결과와 같은 상태와 값을 반환한다. 만약 모든 Promise 객체가 rejected 상태가 되어버리면 AggregateError라고 하는 에러를 작업 실패 정보로 갖고 rejected 상태가 된다. any라는 단어의 뜻처럼 배열 속의 Promise 객체 중 단 하나라도 fulfilled 상태가 되면 되는 것이다.

const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, "quick"));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, "slow"));

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value));

// expected output: "quick"

// any 메소드의 거부
const pErr = new Promise((resolve, reject) => {
  reject("Always fails");
});

Promise.any([pErr]).catch((err) => {
  console.log(err);
});
// expected output: "AggregateError: No Promise in Promise.any was resolved"

0개의 댓글