Promise.all

.esc·2021년 2월 28일
0

Promise.all

복수의 URL에 동시에 요청을 보내고, 모두 처리가 완료되길 기다려야 할때 Promise.all을 사용할 수 있다.

  • 복수의 promise
let promise = Promise.all([...promises...]);

배열 안 promise가 모두 처리되면, 그 결괏값을 담은 배열이 새로운 promise의 result가 된다.

  • result 배열
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

result 배열의 순서는 Promise.all의 promise 순서와 동일하다.
첫번째 promise가 가장 늦게 이행되더라도 처리 결과는 배열의 첫번째에 저장된다.


데이터가 담긴 배열

작업해야 할 데이터가 담긴 배열을 promise 배열로 매핑하고, 이 배열을 Promise.all로 감싸는 트릭은 자주 사용된다.

  • 예시1
let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://api.github.com/users/jeresig'
];
let requests = urls.map(url => fetch(url));

Promise.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));
  1. url배열을 fetch를 사용해 promise로 매핑한다.
  2. promise배열을 Promise.all로 감싼다.
  3. Promise.all은 모든 promise 작업이 이행될 때까지 기다린다.
  • 예시2
let names = ['iliakan', 'remy', 'jeresig'];
let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));

Promise.all(requests)
  .then(responses => {
    for(let response of responses) {
      alert(`${response.url}: ${response.status}`);
    }
    return responses;
  })
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(users => users.forEach(user => alert(user.name)));
  1. 데이터가 담긴 배열이 있다.
  2. fetch를 사용해 promise로 매핑한다.
  3. Promise.all로 감싼다.
  4. promise 응답이 모두 성공적으로 처리되면
  5. for...of로 result 배열 값을 하나씩 꺼내 반복문 수행한다.
  6. result 배열을 json으로 파싱하고 매핑하여 Promise.all로 감싼다.
  7. 파싱된 json이 users 배열에 저장된다.
  8. forEach로 users 배열 값을 하나씩 alert창에 출력한다.

거부된 promise

Promise.all에 전달되는 promise 중 하나라도 거부되면, Promise.all이 전체가 거부되고, 이행된 promise 결과도 무시된다.

Promise.all([
  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))
]).catch(alert); // Error: 에러 발생!
  1. 2초 후 두번째 promise가 거부
  2. Promise.all 전체가 거부
  3. .catch가 실행

Promise.all + await

let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);

참조

https://ko.javascript.info/promise-api

profile
front-end

0개의 댓글