자바스크립트

Section 14. 자바스크립트 프로미스의 병렬 진행

포칼이 2023. 4. 10. 11:46
// 다섯 주자들이 동시에 질주
// 데드라인(밀리초) 안에 들어오지 못하면 탈락
let DEADLINE = 1450;

function getRunPromise (name) {
  return new Promise((resolve, reject) => {
    const time = 1000 + Math.random() * 500;

    setTimeout(() => {
      if (time < DEADLINE) {
        console.log(`🚩 ${name} 도착 - ${(time)/1000}초`);
        resolve({name, time});

      } else {
        reject((`${name} 시간초과`));
      }
    }, time);
  });
}
console.log(
  '철수,영희,돌준,정아,길돈'
  .split(',')
  .map(getRunPromise)
);

주자가 한꺼번에 달려서 통과하지 못하면 애러가 출력된다. 

이렇게 배열을 .map했다. 결국 출력문은 Promise 5개의 각각의 결과가 출력된 것이다. 

 

여러 프로미스를 병렬 처리하기 위한 Promise의 정적 메서드들은 다음과 같다

1. all

  • 프로미스의 배열을 받아 동시에 진행
  • 모두 성공하면 resolve된 값들을 배열로 반환한다. - then 으로 받는다.
  • 하나라도 실패하면 catch 가 실행 된다. 
// 한 명이라도 탈락하면 전체 탈락
Promise.all(
  '철수,영희,돌준,정아,길돈'
  .split(',')
  .map(getRunPromise)
)
.then(console.log)
.catch(console.error)
.finally(() => {
  console.log('- - 경기 종료 - -');
});

정아일때 실패하여 catch가 실행되고 finally 실행 후에 종료가 된 것을 볼 수 있다.

 

2. allSettled

  • 주어진 프로미스들의 결과를 배열로 출력한다.
  • 실패 유무 관계없이 then 으로 배열을 반환한다.
Promise.allSettled(
  '철수,영희,돌준,정아,길돈'
  .split(',')
  .map(getRunPromise)
)
.then(console.log)
// ⚠️ catch는 동작하지 않음
.finally(() => {
  console.log('- - 경기 종료 - -');
});

실패의 유무와 관계없이  then으로 배열이 반환이 됐고 catch는 동작하지 않는다.

 

3. any

  • 가장 먼저 성공한 프로미스의 경과를 then으로 반환한다.
  • 모두 실패시 오류 발생
DEADLINE = 1050;
Promise.any(
  '철수,영희,돌준,정아,길돈'
  .split(',')
  .map(getRunPromise)
)
.then(console.log)
// ⚠️ 모두 실패해도 catch는 동작하지 않음
.finally(() => {
  console.log('- - 경기 종료 - -');
});

가장 먼저 들어온 철수가 then으로 반환이 되어 출력된 것을 볼 수 있다.

 

4. race

성공이든 실패든 첫 결과물 then 또는 catch로 반환한다.

// 다섯 주자들이 선택한 도착지로 질주
// 도착지에 '꽝'이 있으면(50% 확률) 실패
function getBombRunPromise (name) {
  return new Promise((resolve, reject) => {
    const time = 1000 + Math.random() * 500;

    setTimeout(() => {
      console.log(`🚩 ${name} 도착 - ${(time)/1000}초`);
      if (Math.random() < 0.5) {
        resolve((`🙌 ${name} 승리!`));
      } else {
        
        reject((`💣 ${name} 꽝!`));
      }
    }, time);
  });
}
Promise.race(
  '철수,영희,돌준,정아,길돈'
  .split(',')
  .map(getBombRunPromise)
)
.then(console.log)
.catch(console.error)
.finally(() => {
  console.log('- - 경기 종료 - -');
});

첫 결과물이 catch로 반환된 것을 볼 수 있다.