복수의 URL에 동시에 요청을 보내고, 모두 처리가 완료되길 기다려야 할때 Promise.all을 사용할 수 있다.
let promise = Promise.all([...promises...]);
배열 안 promise가 모두 처리되면, 그 결괏값을 담은 배열이 새로운 promise의 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로 감싸는 트릭은 자주 사용된다.
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}`)
));
- url배열을 fetch를 사용해 promise로 매핑한다.
- promise배열을 Promise.all로 감싼다.
- Promise.all은 모든 promise 작업이 이행될 때까지 기다린다.
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)));
- 데이터가 담긴 배열이 있다.
- fetch를 사용해 promise로 매핑한다.
- Promise.all로 감싼다.
- promise 응답이 모두 성공적으로 처리되면
- for...of로 result 배열 값을 하나씩 꺼내 반복문 수행한다.
- result 배열을 json으로 파싱하고 매핑하여 Promise.all로 감싼다.
- 파싱된 json이 users 배열에 저장된다.
- forEach로 users 배열 값을 하나씩 alert창에 출력한다.
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: 에러 발생!
- 2초 후 두번째 promise가 거부
- Promise.all 전체가 거부
- .catch가 실행
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);