본문 바로가기
Programming/자바스크립트

[자바스크립트] 프로미스 - 정적 메소드

by 코딩하는 랄로 2023. 11. 6.
728x90

프로미스 체이닝

 

[자바스크립트] 프로미스 - promise chaining

프로미스 핸들러 [자바스크립트] 프로미스 - Promise Handler 프로미스의 개념과 기본 사용법 [자바스크립트] 프로미스 - 개념 & 기본 사용법 프로미스의 탄생 : 콜백지옥 자바스크립트에서는 서버에

codingralro.tistory.com

 

저번 포스팅에서는 프로미스 체이닝에 대해서 알아보았는데, 이번 포스팅은 프로미스를 좀 더 잘 활용하기 위해 프로미스의 정적 메소드에는 어떠한 것이 있고 어떻게 사용하는지에 대해 공부해보겠다.

 

 

프로미스 정적 메소드

프로미스 객체는 new Promise() 생성자 함수 외에도 여러 가지 정적 메소드를 제공하고 있다. 정적 메소드는 객체를 초기화하지 않고도 바로 사용할 수 있는 메소드로 비동기 처리를 보다 호율적이고 간편하게 구현할 수 있도록 도와준다.

 

Promise.resolve()

resolve라는 메소드는 이전까지는 프로미스를 생성자로 만들고 그 안의 콜백함수의 매개변수를 통해 호출하여 사용해왔다.

function promise() {
    return new Promise((resolve, reject) => {
        resolve('javascript')
    });
}

 

해당 메소드는 프로미스 객체 내에서만 사용이 가능하다는 단점이 존재한다. 하지만 정적 메소드인 Promise.resolve를 사용한다면 프로미스와 전혀 연관없는 함수 내에서 필요에 따라 프로미스 객체를 반환하여 핸들러를 이용할 수 있게 된다.

 

그렇기 때문에 비동기 작업을 수행하지 않는 함수에서도 프로미스의 장점을 활용할 수 있게 된다.

// fulfilled된 프로미스 객체를 반환
function printPromise() {
    let str = 'javascript';
    return Promise.resolve(str);
}

printPromise()
    .then((value) => {
        console.log(value);  //javascript
    })
    .catch((error) => {
        console.error(error);
    })

 

 

Promise.reject()

resolve와 사용 방법은 똑같지만, rejected된 프로미스 객체를 반환한다.

// fulfilled된 프로미스 객체를 반환
function printPromise() {
    let str = 'rejected';
    return Promise.reject(str);
}

printPromise()
    .then((value) => {
        console.log(value);
    })
    .catch((error) => {
        console.error(error);  // rejected
    })

 

 

Promise.all()

배열, Map, Set에 포함된 여러개의 프로미스 요소들을 한꺼번에 비동기 작업을 처리해야 할 때 굉장히 유용한 정적 메소드이다. 모든 비동기 처리가 이행될때까지 기다려서, 완료되면 그 때 then 핸들러가 실행된다.

 

대표적인 사용 예시로는 여러 개의 API 요청을 보내고 모든 응답을 받아야 하는 경우에 유용하게 사용할 수 있다.

// 1. 서버 요청 API 프로미스 객체 생성 (fetch)
const api_1 = fetch("https://...");  // => result1
const api_2 = fetch("https://...");  // => result2
const api_3 = fetch("https://...");  // => result3

// 2. 프로미스 객체들을 묶어 배열로 구성
const promises = [api_1, api_2, api_3];

// 3. Promise.all() 메서드 인자로 프로미스 배열을 넣어, 
// 모든 프로미스가 이행될 때까지 기다리고 결과값을 출력
Promise.all(promises)
    .then((results) => {
      // results는 이행된 프로미스들의 값들을 담은 배열.
      // results의 순서는 promises의 순서와 일치.
      console.log(results); // [result1, result2, result3]
    })
    .catch((error) => {
      // 어느 하나라도 프로미스가 거부되면 오류를 출력
      console.error(error);
    });

 

 

Promise.allSettled()

Promise.all() 메서드의 업그레이드 버전으로, 주어진 모든 프로미스가 처리되면 모든 프로미스 각각의 상태와 값 또는 거부 사유를 모아 놓은 배열을 반환한다.

// 1초 후에 1을 반환하는 프로미스
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 1000));

// 3초 후에 에러를 발생시키는 프로미스
const p2 = new Promise((resolve, reject) => setTimeout(() => reject(new Error('error')), 3000));

// 2초 후에 3을 반환하는 프로미스
const p3 = new Promise(resolve => setTimeout(() => resolve(3), 2000));

// 결과값을 배열에 담아 넘겨줌
// 프로미스 배열에 담긴 순서에 맞게 결과도 담김 <= 완료 또는 거부되는 시간과 관련X
Promise.allSettled([p1, p2, p3]) 
	.then(result => console.log(result));

/*
[
  { status: 'fulfilled', value: 1 },
  {
    status: 'rejected',
    reason: Error: error
        at Timeout._onTimeout (에러 발생 경로)
        at listOnTimeout (node:internal/timers:557:17)
        at processTimers (node:internal/timers:500:7)
  },
  { status: 'fulfilled', value: 3 }
]
*/

 

 

Promise.any()

Promise.all() 메소드와는 반대로, Promise.any() 는 주어진 프로미스 중 하나라도 fulfilled(이행) 상태가 되면 바로 반환하는 정적 메소드이다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("promise1 failed");
    }, 3000);
  });
  
  const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("promise2 succeeded");
    }, 2000);
  });
  
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("promise3 failed");
    }, 1000);
  });
  
  // promise1, promise2, promise3은 각각 3초, 2초, 1초 후에 거부되거나 이행
  Promise.any([promise1, promise2, promise3])
    .then((value) => {
      console.log(value); // promise2 succeeded
    })
    .catch((error) => {
      console.error(error);
    });

 

Promise.any 메소드는 처음 이행된 프로미스만을 취급하기 때문에 promise1이 3초 뒤에 이행되든 말든 신경쓰지 않고 promise2만을 취급한다.

 

만일 모든 프로미스가 rejected되면, AggregateError 객체를 사유로 하는 거부 프로미스를 반환한다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("promise1 failed");
    }, 3000);
  });
  
  const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject("promise2 failed");
    }, 2000);
  });
  
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("promise3 failed");
    }, 1000);
  });
  
  Promise.any([promise1, promise2, promise3])
    .then((value) => {
      console.log(value);
    })
    .catch((error) => {
      console.error(error); // AggregateError: All promises were rejected
      console.error(error.errors); // [ 'promise1 failed', 'promise2 failed', 'promise3 failed' ]
    });

 

 

Promise.race()

Promise.any() 메소드와 유사하게 가장 먼저 처리된 프로미스의 결과값을 반환한다. Promise.any는 fulfilled 상태가 된 프로미스를 반환하거나 전부 rejected가 되면 에러 객체를 반환하지만, Promise.race는 fulfilled, rejected 상태 상관없이 무조건 가장 먼저 처리가 끝난 프로미스 결과값을 반환한다.

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("promise1 failed");
    }, 3000);
  });
  
  const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("promise2 succeeded");
    }, 2000);
  });
  
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("promise3 failed");
    }, 1000);
  });
  
  // any() : 가장 먼저 이행된 프로미스 결과값을 반환
  // 모두 rejected => AggregateError
  // promise3이 가장 먼저 이행되지만 rejected이므로 무시
  // 그 다음 이행되는 promise2를 반환
  Promise.any([promise1, promise2, promise3])
    .then((value) => {
      console.log(value); // promise2 succeeded
    })
    .catch((error) => {
      console.error(error); 
    });

  // race() : 가장 먼저 처리된 프로미스 결과값을 반환
  // fulfilled, rejected 여부 상관 없음
  // promise3이 가장 먼저 처리되므로 promise3를 반환
  Promise.race([promise1, promise2, promise3])
    .then((value) => {
        console.log(value);
    })
    .catch((error) => {
        console.error(error); // promise3 failed
    })

 

 

 

 

reference : Inpa dev

728x90