개인공부/TIL(Today I Learned)

TIL 57일차_Promise.all

soon327 2021. 3. 16. 01:13

Promise.all ?

복수의 URL에 동시에 요청을 보내고, 다운로드가 모두 완료된 후에 콘텐츠를 처리하고 싶을 때,
Promise.all을 사용한다.

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

Promise.all은 전체가 프라미스인 배열( 엄밀히 따지면 이터러블 객체이지만, 대개는 배열이다)을 받고
새로운 프라미스를 반환한다.
이 때, 반환되는 새로운 프라미스 배열의 순서는 전달된 프라미스 순서와 일치한다.
즉, Promise.all의 첫번째 프라미스가 가장 늦게 이행되더라도, 처리결과는 배열의 첫번째 요소에 저장된다.

Promise.all 사용

  1. 작업해야할 데이터가 담긴 배열을 프라미스 배열로 매핑하고,
    이 배열을 Promise.all 로 감싸는 트릭은 굉장히 자주 사용된다.
let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://api.github.com/users/jeresig'
];

// fetch를 사용해 url을 프라미스로 매핑합니다.
let requests = urls.map(url => fetch(url));

// Promise.all은 모든 작업이 이행될 때까지 기다립니다.
Promise.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));
  1. 순서가 필요없는 여러개의 비동기처리를 병렬로 빠르게 하고 싶을 때

순서에 상관없이 여러개의 비동기처리를 병렬로 빠르게 처리하고 싶을때 Promise.all이 사용된다.

Promise.all 코드에서 display(3000), display(2000), display(1000)가
차례대로 앞의 함수의 실행이 완료되는 것을 기다리지 않고 비동기적으로 병렬로 실행된다.
여기서 눈여겨볼 점은 "순서대로 실행되지만, 앞의 함수가 완료되는 것을 기다리지 않는다"는 것이다.

그리고 마지막으로 완료되는 함수까지 기달려다가 값을 반환한다.
이때 반환 순서는 실행 순서와 동일하게 하다(완료 순서가 아니다!).

  1. 빠른 에러 처리

위에서 말했듯이
Promise.all함수를 사용한 경우 비동기 함수가 병렬로 실행되기 때문에
실행 순서와는 상관없이 가장 빨리 에러를 반환하는 함수의 시간을 기준으로 동작이 종료된다.
그래서 빠르게 에러 처리가 가능하다.

Promise.all에서는 전달되는 프라미스 중 하나라도 거부되면 Promise.all 전체가 거부되고,
.catch가 실행된다. 그동안 배열에 저장된 다른 프라미스의 결과는 완전히 잊혀지고, 이행된 프라미스의 결과도 무시된다.

다시말해,
Promise.all은 프라미스가 하나라도 거절되면 전체를 거절하므로,
프라미스 결과가 모두 필요할 때와 같은 경우 유용하다.

참고: javascript.info
Jacob's Development Blog