aotoyae

[JS] 프로미스 Promise(2) Promise.all, Promise.race, 프로미스 체이닝 본문

JavaScript

[JS] 프로미스 Promise(2) Promise.all, Promise.race, 프로미스 체이닝

aotoyae 2023. 12. 15. 01:11

 

 

복습!

 

const pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("OK");
    // reject(new Error("ERROR")); resolve를 지우고 이 부분을 쓰면 Error가 뜬다.
  }, 1000);
});

console.log("START");

pr.then((result) => {
  console.log(result);
})
  .catch((err) => {
    console.log(err);
  })
  .finally(() => {
    console.log("END");
  });

// "START"
// 1초 후 "OK"
// "END"

 

const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("1번 주문 완료");
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("2번 주문 완료");
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(function () {
      res("3번 주문 완료");
    }, 2000);
  });
};

console.log("시작");
f1() // 프로미스 반환
  .then((res) => f2(res)) // res 함수를 실행하며 반환된 값을 f2로 넘겨줌
  .then((res) => f3(res))
  .then((res) => console.log(res))
  .catch(console.log)
  .finally(() => {
    console.log("끝");
  });

// "시작"
// 1초 후 "1번 주문 완료"
// 3초 후 "2번 주문 완료"
// 2초 후 "3번 주문 완료"
// "끝"

 

이런 식으로 then. catch 등 으로 연결 되는 걸

❗️ 프로미스 체이닝이라 한다! Promise chaining

 

 

만약 f2에서 실패가 뜨면? (위 코드에서 f2 부분만 수정)

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() => {
      rej("에러");
    }, 3000);
  });
  
// "시작"
// 1초 후 "1번 주문 완료"
// 3초 후 "에러"
// "끝"

 

❗️ 그 다음 코드(f3)은 실행되지 않고 끝난다.

 

 

실행되는 시간은 줄일 수 없을까?

Promise.all 을 사용한다!

const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("1번 주문 완료");
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("2번 주문 완료");
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(function () {
      res("3번 주문 완료");
    }, 2000);
  });
};

console.time("x");
Promise.all([f1(), f2(), f3()]).then((res) => {
  console.log(res);
  console.timeEnd("x");
});

// undefined
// undefined
// 3초 후 ['1번 주문 완료', '2번 주문 완료', '3번 주문 완료']
// x: 3002.675048828125 ms

 

가장 긴 시간이 걸렸던 f2의 시간만큼 걸린다.

 

❗️ Promise.all의 주의할 점은 하나가 reject를 반환한다면,

다른 resolve 값은 모두 반환되지 않고 그 reject만 반환된다. (위 코드에서 f2 부분만 수정)

>> 하나의 정보라도 누락될 경우 페이지를 보여주면 안될 때 사용한다.

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() => {
      rej(new Error("에러"));
    }, 3000);
  });
};

// undefined
// undefined
// 3초 후 Uncaught (in promise) Error: 에러

 

Promise.race

❗️ Promise.all과 달리 하나라도 완료된 게 있다면 완료된 값을 반환한다.

>> 용량이 큰 이미지들을 로딩할 때 하나라도 완료된 걸 먼저 보여줄 때 사용한다.

const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("1번 주문 완료");
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() => {
      rej(new Error("에러"));
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(function () {
      res("3번 주문 완료");
    }, 2000);
  });
};

Promise.race([f1(), f2(), f3()]).then((res) => {
  console.log(res);
});

// undefined
// undefined
// 1초 후 "1번 주문 완료"

 

 

 

🔗 https://youtu.be/3Ao3OroqQLQ?si=VK4cV-ahBCLm4_Gs