본문 바로가기
개발/JavaScript

자바스크립트 프로미스 - Promise all, race

by 피로물든딸기 2021. 7. 31.
반응형

자바스크립트 전체 링크

 

Promise.all을 이용하면 여러 개의 프로미스를 병렬로 처리한다.

비동기 함수 간에 서로 의존성이 없는 경우 사용할 수 있다.

 

아래 getData는 동시에 실행된다.

function getData(response, number) {
    return new Promise((resolve, reject) => {
        if(response) resolve(`resolve ${response} ${number}`);
        else reject(`reject ${response}`); // or reject(new Error(`reject Error! ${response}`));
    }); 
}

getData(true, 1).then(result => console.log(result));
getData(true, 2).then(result => console.log(result));

 

프로미스를 병렬로 처리하면 아래와 같이 사용할 수 있다.

function getData(response, number) {
    return new Promise((resolve, reject) => {
        if(response) resolve(`resolve ${response} ${number}`);
        else reject(`reject ${response}`); // or reject(new Error(`reject Error! ${response}`));
    }); 
}

Promise.all([getData(true, 1), getData(true, 2)])
.then(
    ([result1, result2]) => console.log(`success ${result1} ${result2}`), 
    (result1) => console.log(`error ${result1}`)
);

 

Promise.all 함수도 프로미스를 반환한다.

따라서 모든 함수가 작업이 완료되어야 처리 상태가 반환된다.

 

getData 중 하나를 reject이 호출되게 하면 아래와 같이 error 로그가 출력된다.

Promise.all([getData(false, 1), getData(true, 2)])
.then(
    ([result1, result2]) => console.log(`success ${result1} ${result2}`), 
    (result1) => console.log(`error ${result1}`)
);


Promise.race를 이용하면 여러 개의 프로미스 중 가장 먼저 처리된 프로미스를 반환한다.

입력된 프로미스 중 하나라도 처리되면 Promise.race가 반환하는 프로미스도 resolve를 호출하게 된다.

 

getData에 time을 추가하여 time ms뒤에 resolve가 호출되도록 수정해보자.

function getData(response, number, time) {
    return new Promise((resolve, reject) => {
        if(response) setTimeout(() => resolve(`resolve ${response} ${number}`), time);
        else reject(`reject ${response}`); // or reject(new Error(`reject Error! ${response}`));
    }); 
}

Promise.race([getData(true, 1, 500), new Promise((_, reject) => setTimeout(reject, 1000))])
.then((result1) => console.log(`success ${result1}`))
.catch((error) => console.log(`error ${error}`));

 

getData의 resolve가 500ms 뒤에 호출되므로, 먼저 프로미스로 반환되고, then이 호출된다.

2000ms뒤에 호출되도록 하면 catch가 호출된다.

Promise.race([getData(true, 1, 2000), new Promise((_, reject) => setTimeout(reject, 1000))])

 

getData가 먼저 호출되더라도 reject를 호출하게 하면, catch가 호출된다. (true → false)

Promise.race([getData(false, 1, 500), new Promise((_, reject) => setTimeout(reject, 1000))])


데이터 캐싱

 

데이터 캐싱은

처음에는 DB에서 data를 가지고 오지만, 이후에는 프로그램 종료 전 까지 캐시에 저장된 data를 사용한다.

 

getData가 DB, server 등등에서 data를 가져온다고 가정하자.

매번 getData를 호출하면 비용이 많이 들기 때문에 아래와 같이 cache에 저장할 수 있다.

function getData(response, number, time) {
    console.log(`--- getData ---`);
    return new Promise((resolve, reject) => {
        if(response) setTimeout(() => resolve(`resolve ${response} ${number}`), time);
        else reject(`reject ${response}`); // or reject(new Error(`reject Error! ${response}`));
    }); 
}

let cacheMemory;
function getMemory() {
    cacheMemory = cacheMemory || getData(true, 1, 1000);
    return cacheMemory;
}

getMemory().then(v => console.log(v));
getMemory().then(v => console.log(v));
getMemory().then(v => console.log(v));

 

getMemory는 최초 한번만 getData를 호출하고 이후는 cacheMemory를 참조한다.

반응형

댓글