비동기 처리 - 1. 비동기와 콜백 글 보러 가기 

비동기 처리 - 2.  Promise 글 보러 가기 

비동기 처리 - 3.  Promise Chaining | Error Handling 글 보러 가기 

 


 

개요

 

프라미스 API

 

ko.javascript.info

 


 

1. Promise.all

의미 

전달된 프로미스가 모두 요청 이행되면 (하나라도 거부되면 안 됨), 그 결과를 배열로 묶어서 리턴해주는 API

 

필요성
  • 2개 이상의 프로미스를 동시에 실행시키고, 모든 프로미스가 준비될 때까지 기다려야 할 때 사용
  • 예시 : 복수의 URL에 동시 요청 보내고, 다운로드가 모두 완료된 후에 콘텐츠를 처리

 

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

// 간단 예시 
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 에 전달되는 프로미스 중 하나라도 거부되면, Promise.all 이 반환하는 프로미스는 에러와 함께 거부됨
    → 그러나 이는 지나치게 극단적. 일부 성공 + 일부 실패를 리턴해주는 Promise.allSettled 있음
  • 이터러블 객체가 아닌 일반 값도 Promise.all(iterable)에 넘길 수 있음

 

예시 코드 
Promise.all([
  faceapi.nets.tinyFaceDetector.loadFromUri('static/tensorflow-models'),
  faceapi.nets.faceLandmark68TinyNet.loadFromUri('static/tensorflow-models'),
  //faceapi.nets.faceExpressionNet.loadFromUri('static/tensorflow-models'),
  //faceapi.nets.ageGenderNet.loadFromUri('static/tensorflow-models'),
  faceapi.nets.faceRecognitionNet.loadFromUri('static/tensorflow-models'),
]).then(() => {
  faceapi.env.monkeyPatch({
      Canvas: HTMLCanvasElement,
      Image: HTMLImageElement,
      ImageData: ImageData,
      Video: HTMLVideoElement,
      createCanvasElement: () => document.createElement('canvas'),
      createImageElement: () => document.createElement('img')
  })
  FaceDetector.isFaceapiLoaded = true;
});

 


 

2. Promise.allSettled

의미

일부 요청 성공 결과 + 일부 요청 실패 결과를 모두 리턴 해주는 (일부 실패해도 됨) API

 

예시 코드
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: ...에러 객체...}
]
  • 브라우저 버전이 오래되어 Promise.allSettled 를 지원하지 않는 경우 폴리필을 구현해야 함
  • 폴리필 : 오래된 웹 브라우저에서 최신 기술 및 API를 지원할 수 있도록 하는 코드 또는 스크립트
// 구현한 폴리필 예시 
if(!Promise.allSettled) {
  Promise.allSettled = function(promises) {
    return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({
      status: 'fulfilled',
      value
    }), reason => ({
      status: 'rejected',
      reason
    }))));
  };
}

 


 

2. Promise.race

의미

가장 먼저 처리되는 프로미스의 결과 (이행 or 거부) 를 리턴하는 API

 

예시 코드
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

// 프로젝트에 적용 
return Promise.race([
  fetch(resource, Object.assign({signal}, init)).then(response => {  //fetch 함수를 이용하여 네트워크 리소스에 대한 요청 수행 
      clearTimeout(timeoutID);  //fetch 요청이 완료되면 타임아웃을 취소하기 위해 사용됨
      return response;
  }),
  new Promise((resolve, reject) => {
      timeoutID = setTimeout(() => {
          if (controller) controller.abort();
          reject(new Error(`Fetch timed out after ${timeout} ms`));
      }, timeout);
  })
]);
  • Promise.resolve Promise.reject 는 async, await 구문으로 대체 됨

+ Recent posts