Promise.all()
Promise.all()은 여러 개의 비동기 작업을 병렬(순서를 보장하지 않음)로 실행시키는 경우 사용된다.
여러 개를 동시에 실행하고 가장 마지막 작업이 완료될 때 완료 상태의 프로미스를 반환한다.
const myPromises = [
new Promise((resolve) => setTimeout(() => {resolve('A (slow)'); console.log('A (slow)')}, 1000)),
new Promise((resolve) => setTimeout(() => {resolve('B (slower)'); console.log('B (slower)')}, 2000)),
new Promise((resolve) => setTimeout(() => {resolve('C (fast)'); console.log('C (fast)')}, 10))
];
Promise.all(myPromises).then(console.log)
// C (fast)
// A (slow)
// B (slower)
위의 코드를 보면, 각각 1초, 2초, 0.01초 딜레이 후 콘솔을 출력하는 프로미스 A, B, C가 있다.
각 작업은 A, B, C 순으로 병렬 실행되지만, 작업에 걸리는 시간으로 예상할 수 있듯이 C, A, B 순으로 콘솔 로그가 찍히게 된다.
다시말해, Promise.all()은 작업의 시작 순서가 완료의 순서를 보장하지 않는다.
따라서, 실행할 비동기 작업들의 순서가 중요하지 않은 경우에만 Promise.all을 사용해야 한다.
ex) 여러 데이터를 패칭하는 경우
그리고 하나의 Promise라도 거절(rejected) 상태를 가진다면, Promise.all()은 에러(.catch)로 반환된다는 특징도 있다.
하지만, 여러 개의 비동기 작업을 순서대로 실행시키고 싶은 경우가 있다.
Array.prototype.reduce()
배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);
reduce 사용의 대표적인 예는 아래와 같은 누적합 구하기이다.
const array1 = [1, 2, 3, 4];
// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array1.reduce(
(accumulator, currentValue) => accumulator + currentValue,
initialValue
);
console.log(sumWithInitial);
// Expected output: 10
이전의 연산값(누적값)에 현재값을 연산하여 다음 연산을 위해 결과를 반환시킨다.
reduce 로직을 이용하면, 여러 개의 프로미스를 순서를 보장하며 실행시킬 수 있다.
const myPromises = [
new Promise((resolve) => setTimeout(() => {resolve('A (slow)')}, 1000)),
new Promise((resolve) => setTimeout(() => {resolve('B (slower)')}, 2000)),
new Promise((resolve) => setTimeout(() => {resolve('C (fast)')}, 10))
];
myPromises.reduce((promise, currentPromise) => {
return promise.then(async() => {
const result = await currentPromise;
console.log(result); // 순서를 보장해야하는 작업 수행
return result;
});
}, Promise.resolve());
// A (slow)
// B (slower)
// C (fast)
Promise.all의 코드를 reduce를 사용하여 Promise를 순차적으로 수행(A->B->C)하는 코드로 수정해보았다.
- 초기값 : Promise.resolve() [빈 resolve]
- 누적값(promise) : 이전 Promise가 성공했을 때, 현재 Promise를 반환
- 현재값(currentPromise) : myPromises의 각 요소
초기값으로 빈 resolve를 주고, 바로 다음 단계에서 resovle의 콜백에 현재 프로미스를 반환하도록 만든다.
그러면 두 번째 단계에선느 누적값으로 이전 프로미스(A)를 갖고 있게되고, 이전 프로미스(A)의 콜백을 통해 현재 프로미스(B)를 반환하게 한다. 이 때, 현재 Promise(B)를 반환하기 전에, 현재 Promise(B)의 콜백을 이용해서 프로미스 내부 작업(위의 예시 코드에서는 console 로그 찍기)를 수행하면 순서를 보장할 수 있다. 이 작업을 반복함으로써, 프로미스를 순차적으로 실행시킬 수 있는 코드가 완성된다.
Reference
'FrontEnd > HTML5 & CSS & JavaScript' 카테고리의 다른 글
[HTML/CSS] 쉐도우 돔(Shadow DOM) 내부에서 @font-face가 동작하지 않는 이슈 (0) | 2023.06.30 |
---|---|
[HTML/CSS] 쉐도우 돔(Shadow DOM)으로 스타일 충돌 해결하기 (0) | 2023.05.06 |
[css] 모바일 환경(터치 스크린)에서의 hover 이슈 (0) | 2022.09.20 |
[JavaScript] Proxy 객체란? (0) | 2022.05.06 |
[JavaScript] 한글 키보드 입력 시 이벤트가 두 번 호출되는 경우 (2) | 2022.05.02 |
댓글