May 2, 2021 ˑ 6min read
ES6(ECMAScript2015)부터 Promise
가 지원되기 시작하면서 비동기 함수를 편리하게 다룰 수 있게 되었습니다.
Promise
는 단어의 의미대로 어떠한 값을 미래에 돌려준다는 약속을 의미하는데요.
Promise
의 등장 이후 비동기 함수를 동시에 실행할 수 있도록 도와주는 정적 메서드들이 제공되기 시작했습니다.
이번 글에서는 Promise
의 동시성 처리를 위해 제공되는 정적 메서드에 대해 알아보겠습니다.
Important
동시성(concurrency)
과병렬성(parallelism)
은 비슷한 개념이지만, 엄밀히 보면 차이가 있습니다.JavaScript는 기본적으로
싱글 스레드(Single-threaded)
로 동작하기 때문에Promise.all
을 사용한다고 해서 실제로 병렬 실행이 일어나는 것은 아닙니다. 이벤트 루프를 통해 짧은 시간에 번갈아 실행하는 방식으로 함수들이 병렬로 실행되는 것처럼 보이는 동시성 처리를 지원합니다.
Note여기서
Promise
의 완료는 성공(resolve
)또는 실패(reject
)되어 결과값이나 에러를 반환한 상태를 의미합니다.
Promise
가 지원되기 시작한 ES6부터 Promise.all
메서드도 함께 지원되기 시작했습니다.
인자로 받은 Promise
배열이 모두 성공(resolve
)한 경우 결과값의 배열을 반환하며, 하나의 Promise
라도 실패(reject
)한 경우 즉시 완료되어 에러를 발생합니다.
해당 메서드는 모든 비동기 작업이 반드시 성공해야 다음 작업이 진행될 수 있는 경우 유용하게 사용할 수 있습니다.
// e.g. 성공 케이스
const p1 = () => Promise.resolve(1);
const p2 = () => Promise.resolve(2);
const p3 = () => Promise.resolve(3);
Promise.all([p1(), p2(), p3()])
.then(results => console.log('결과:', results))
.catch(error => console.error('에러:', error));
// [console] "결과: [1, 2, 3]"
// e.g. 실패 케이스
const p1 = () => Promise.resolve(1);
const p2 = () => Promise.resolve(2);
const p3 = () => Promise.reject('에러 발생');
Promise.all([p1(), p2(), p3()])
.then(results => console.log('결과:', results))
.catch(error => console.error('에러:', error));
// [console] "에러: 에러 발생"
Promise.all
과 함께 ES6 부터 제공된 Promise.race
는 가장 먼저 완료된 Promise
의 결과값을 반환하는 특징을 갖고 있습니다.
가장 먼저 실패(reject
)한 경우에도 즉시 완료처리되어 에러를 발생하기 때문에 예외처리를 주의해야합니다.
// e.g. 성공 케이스
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 3000));
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 2000));
const p3 = new Promise(resolve => setTimeout(() => resolve(3), 1000));
Promise.race([p1, p2, p3])
.then(result => console.log('결과:', result))
.catch(error => console.error('에러:', error));
// [console] 3
// e.g. 실패 케이스
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 3000));
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 2000));
const p3 = new Promise(resolve => setTimeout(() => reject('에러 발생'), 1000));
Promise.race([p1, p2, p3])
.then(result => console.log('결과:', result))
.catch(error => console.error('에러:', error));
// [console] "에러: 에러 발생"
Promise.allSettled
는 ES11에 추가된 정적 메소드로 인자로 전달된 Promise
배열의 성공/실패 여부와 상관없이 항상 결과값을 반환합니다.
실패한 Promise
도 결과값을 확인할 수 있기 때문에 개별적인 처리가 필요한 경우 유용하게 사용할 수 있습니다.
const p1 = Promise.resolve(1);
const p2 = Promise.reject('에러 발생');
const p3 = Promise.resolve(3);
Promise.allSettled([p1, p2, p3])
.then(results => console.log('결과:', results));
/* [console]
[
{ status: "fulfilled", value: 1 },
{ status: "rejected", reason: "에러 발생" },
{ status: "fulfilled", value: 3 }
]
*/
Promise.any
는 비교적 최근인 ES12에 추가되었습니다. Promise.race
와 비슷하지만, 빠르게 성공(resolve
)한 값을 결과값으로 사용한다는 점에서 차이가 있습니다.
그렇다면 실패한 Promise
에 대한 처리가 궁금하실 텐데요. 만약 인자로 받은 모든 Promise
가 실패(reject
)한 경우 다수의 에러를 하나의 에러로 처리하는 ArrgegateError 를 발생합니다.
실패(reject
)한 Promise가 있더라도 성공(resolve
)한 Promise
가 있는 경우 결과값을 반환하기 때문에 유용하게 사용할 수 있습니다.
// e.g. 성공 케이스
const p1 = new Promise((_, reject) => setTimeout(() => reject("에러 발생"), 100));
const p2 = new Promise(resolve => setTimeout(() => resolve("성공"), 200));
const p3 = new Promise((_, reject) => setTimeout(() => reject("에러 발생"), 300));
Promise.any([p1, p2, p3]).then(console.log);
// [console] "성공"
// e.g. 실패 케이스
const p1 = new Promise((_, reject) => setTimeout(() => reject("에러 발생"), 100));
const p2 = new Promise((_, reject) => setTimeout(() => reject("에러 발생", 200));
Promise.any([p1, p2])
.then(console.log)
.catch(console.error);
// [console] AggregateError: All promises were rejected
메서드 | 반환 조건 | 실패 처리 | 사용 예시 |
---|---|---|---|
Promise.all | 모든 Promise가 성공하면 결과 반환 | 하나라도 실패하면 reject | 모든 요청이 성공해야 하는 경우 |
Promise.allSettled | 모든 Promise가 완료되면 결과 반환 | 실패한 경우도 결과에 포함 | 성공/실패 여부 상관없이 모든 결과 필요할 때 |
Promise.race | 가장 먼저 완료된 Promise를 반환 | 먼저 완료된 Promise가 실패면 즉시 reject | 가장 빠른 응답을 선택해야 할 때 |
Promise.any | 가장 먼저 성공한 Promise를 반환 | 모든 Promise가 실패하면 AggregateError | 여러 개 중 하나라도 성공하면 되는 경우 |
이번 글에서는 비동기 함수의 동시성 처리를 위한 메서드들에 대해 알아보았습니다.
각 메서드의 특징에 따라 상황에 맞는 적절한 메서드를 사용할 수 있으면 좋겠습니다.
Chrome Extension
Mar 4, 2024
20 min read
크롬, 파이어폭스, 엣지, 오페라와 같은 주요 브라우저는 기능을 확장하거나 수정할 수 있는 확장 프로그램을 개발할 수 있는 환경과 API를 제공합니다. 확장 프로그램은 웹페이지의 UI를 변경하거나, 브라우저 이벤트를 감지하여 필요한 동작을 수행하는 등 다양한 응용이 가능한데요. 이번 글에서는 크롬 브라우저의 확장 프로그램을 개발하기에 앞서 확장 프로그램의 구성에 필요한 파일들과 그 역할에 대해 알아보려고 합니다.
Chrome Extension
May 4, 2024
15 min read
Chrome, Firefox, Edge, Opera 등 주요 브라우저는 기능을 확장하거나 수정할 수 있는 확장 프로그램을 개발할 수 있는 환경과 API를 제공합니다. 확장 프로그램은 웹페이지의 UI를 변경하거나, 브라우저 이벤트를 감지하여 필요한 동작을 수행하는 등 다양한 응용이 가능한데요. 이번 글에서는 크롬 브라우저의 확장 프로그램을 개발하기에 앞서 확장 프로그램에 필요한 파일 구성과 그 역할에 대해 알아보려고 합니다.