Web/HTML CSS JS

Java Script - 비동기 프로그래밍 2 (async, await, Promise API (all, race))

dev_sr 2020. 9. 28. 14:24

promise 를 조금더 간결하게 사용하게 하고

동기적 실행처럼 보이게 해준다.

 

promise chain (then => then => then ..) 을 일반적인 동기적 코드를 작성하는 것처럼

간편하게 해준다.

 

 

 

1. async

 

promise 로 작성시

//1.1 promise
function fetchUser() {
     return new Promise((resolve, reject) => {
        resolve('홍길동');
     });
}

const user = fetchUser();
user.then(console.log);

 

async를 이용하여 작성시

promise를 쓰지 않아도 promise를 리턴하고 비동기 실행한다.

//1.2 async - promise를 쓰지 않아도 promise 비동기 실행
 async function fetchUser() {
     return '홍길동';
 }
 const user = fetchUser();
 user.then(console.log);

 

 

 

 

2. await 

 

promise 를 반환하는 async 가 붙은 함수 안에서만 사용 가능

Axios API(promise 반환)에서 주로 사용

 

async 가 붙은 함수가 실행되고

resolve나 reject 되어서 새로운 Promise가 반환될 때까지 기다려준다.

 

 

예시)

딜레이 후 사과 반환 -> 딜레이 후 바나나 반환 -> 두 리턴값을 합쳐서 출력

이런 구조의 코드가 있다면

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
    await delay(1000); //딜레이가 끝날 때까지 기다림
    return 'apple';
}

async function getBanana() {
    await delay(500);
    return 'banana';
}

 

Promise만 사용할 경우 콜백 지옥이 연상되는 then 지옥이 펼쳐질 수 있다.

function pickFruit() {
    return getApple()
        .then(apple => {
            return getBanana()
                .then(banana => `${apple} + ${banana}`); //콜백지옥이 떠오른다.
        })
}
pickFruit().then(console.log);

 

 

await를 사용할 경우 

async function pickFruit() {

    const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`;
}

pickFruit().then(console.log);

코드가 훨씬 줄어든다.

 

 

 

3. Promise API

 

위의 코드는 병렬적으로 실행되지 않음

사과 (1초) -> 바나나 (1초) : 출력되는데 총 2초가 걸림

 

사과(1초)

바나나(1초)      -> 1초 출력

 

와 같이 병렬적으로 실행하려면 promise를 변수에 담고 await 해서 기다려줌

async function pickFruit() {

    //사과(1초)=> 바나나(1초) =>2초 걸림
    //병렬적으로 실행하기 위해선  : 사과(1초)+바나나(1초)=> 1초
    //1. promise 만들기
    const applePromise = getApple(); //promise는 만들자마자 실행된다.
    const bananaPromise = getBanana();
    const apple = await applePromise; //딜레이를 기다려줌
    const banana = await bananaPromise;
    return `${apple} + ${banana}`;
}

pickFruit().then(console.log);

이럼 딱 1초 걸린다.

 

단점 : 코드가 더러움

 

 

 

1) all

promise 의 all이라는 api를 사용하면 한번에 값을 받아올 수 있다.

all : resolve 나 reject 되어서 값이 다 반환될때까지 기다려면서 반환값을 배열에 담아둔다.

//2. promise all api 활용하기
//배열로 한번에 결과를 받고 새로운 promise를 반환해준다.
function pickAllFruit() {
    return Promise.all([getApple(), getBanana()])
        .then(fruits => fruits.join(' + '));
}

pickAllFruit().then(console.log);

위의 코드처럼 promise를 await하는 것보단 깔끔하게 쓸 수 있다.

 

 

 

 

2) race

resolve 나 reject를 했을 때 가장 먼저 리턴되는 것만 새로운 promise를 반환시켜 전달해준다.

만약 바나나를 가져오는데 0.5초가 걸린다면

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
    await delay(1000); //딜레이가 끝날 때까지 기다림
    return 'apple';
}

async function getBanana() {
    await delay(500);
    return 'banana';
}
//가장 먼저 리턴되는 것만 전달하기
function pickOnlyOne() {
    return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log); //사과(1), 바나나(0.5) => 바나나

 

둘다 1초라면 getApple이 먼저 호출되므로 사과만 출력

 

 

 

 

 

 

참고한 글

 

자바스크립트 async와 await

(중급) 자바스크립트 개발자를 위한 async, await 사용법 설명. 쉽게 알아보는 자바스크립트 async await 개념, 사용법, 예제 코드, 예외 처리 방법

joshua1988.github.io