비동기 처리 - 3. Promise Chaining | Error Handling 글 보러 가기
개요
- 개요는 시리즈 1편과 동일함
- 이하 모든 글의 출처는 https://ko.javascript.info/promise-api
1. Promise.all
의미
전달된 프로미스가 모두 요청 이행되면 (하나라도 거부되면 안 됨), 그 결과를 배열로 묶어서 리턴해주는 API
필요성
- 2개 이상의 프로미스를 동시에 실행시키고, 모든 프로미스가 준비될 때까지 기다려야 할 때 사용
- 예시 : 복수의 URL에 동시 요청 보내고, 다운로드가 모두 완료된 후에 콘텐츠를 처리
문법
let promise = Promise.all([...promises...]);
// 간단 예시
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이 반환됩니다. 각 프로미스는 배열을 구성하는 요소가 됩니다.
처리 과정
- Promise.all 의 결과로 리턴되는 것 : 배열 안 프로미스의 결괏값을 담은 배열
- Promise.all 에 전달되는 프로미스 중 하나라도 거부되면, Promise.all 이 반환하는 프로미스는 에러와 함께 거부됨
→ 그러나 이는 지나치게 극단적. 일부 성공 + 일부 실패를 리턴해주는 Promise.allSettled 있음 - 이터러블 객체가 아닌 일반 값도 Promise.all(iterable)에 넘길 수 있음
예시 코드
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('static/tensorflow-models'),
faceapi.nets.faceLandmark68TinyNet.loadFromUri('static/tensorflow-models'),
//faceapi.nets.faceExpressionNet.loadFromUri('static/tensorflow-models'),
//faceapi.nets.ageGenderNet.loadFromUri('static/tensorflow-models'),
faceapi.nets.faceRecognitionNet.loadFromUri('static/tensorflow-models'),
]).then(() => {
faceapi.env.monkeyPatch({
Canvas: HTMLCanvasElement,
Image: HTMLImageElement,
ImageData: ImageData,
Video: HTMLVideoElement,
createCanvasElement: () => document.createElement('canvas'),
createImageElement: () => document.createElement('img')
})
FaceDetector.isFaceapiLoaded = true;
});
2. Promise.allSettled
의미
일부 요청 성공 결과 + 일부 요청 실패 결과를 모두 리턴 해주는 (일부 실패해도 됨) API
예시 코드
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/Violet-Bora-Lee',
'https://no-such-url'
];
Promise.allSettled(urls.map(url => fetch(url)))
.then(results => { // (*)
results.forEach((result, num) => {
if (result.status == "fulfilled") {
alert(`${urls[num]}: ${result.value.status}`);
}
if (result.status == "rejected") {
alert(`${urls[num]}: ${result.reason}`);
}
});
// 예상 결과
[
{status: 'fulfilled', value: ...응답...},
{status: 'fulfilled', value: ...응답...},
{status: 'rejected', reason: ...에러 객체...}
]
- 브라우저 버전이 오래되어 Promise.allSettled 를 지원하지 않는 경우 폴리필을 구현해야 함
- 폴리필 : 오래된 웹 브라우저에서 최신 기술 및 API를 지원할 수 있도록 하는 코드 또는 스크립트
// 구현한 폴리필 예시
if(!Promise.allSettled) {
Promise.allSettled = function(promises) {
return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({
status: 'fulfilled',
value
}), reason => ({
status: 'rejected',
reason
}))));
};
}
2. Promise.race
의미
가장 먼저 처리되는 프로미스의 결과 (이행 or 거부) 를 리턴하는 API
예시 코드
Promise.race([
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))
]).then(alert); // 예시 결과 : 1
// 프로젝트에 적용
return Promise.race([
fetch(resource, Object.assign({signal}, init)).then(response => { //fetch 함수를 이용하여 네트워크 리소스에 대한 요청 수행
clearTimeout(timeoutID); //fetch 요청이 완료되면 타임아웃을 취소하기 위해 사용됨
return response;
}),
new Promise((resolve, reject) => {
timeoutID = setTimeout(() => {
if (controller) controller.abort();
reject(new Error(`Fetch timed out after ${timeout} ms`));
}, timeout);
})
]);
- Promise.resolve Promise.reject 는 async, await 구문으로 대체 됨
'Backend > Node.js' 카테고리의 다른 글
[Asynchronous] 비동기 처리 - 6. async, await (0) | 2023.12.01 |
---|---|
[Asynchronous] 비동기 처리 - 5. Microtask : 비동기 처리의 메모리 측면 개념 (0) | 2023.12.01 |
[Asynchronous] 비동기 처리 - 3. Promise Chaining | Error Handling (1) | 2023.12.01 |
[Asynchronous] 비동기 처리 - 2. Promise (1) | 2023.12.01 |
[Asynchronous] 비동기 처리 - 1. 비동기와 콜백 (0) | 2023.12.01 |