본문 바로가기
Javascript

Async / Await 주의해서 다루기

by F.E.D 2020. 4. 25.

async / await를 다룰 때 주의해야 할 점입니다.

 

Non Blocking 형태의 I/O 작업을하는 Node.js는 익숙하지 않을 수 있습니다.

 

let printNum = (number, delaySec) => {
    setTimeout(() => console.log(number), delaySec); // i/o 작업을 대신한다.
};

let logPrintNum = (number, delaySec) => {
    console.log(`Enter logPrintNum ${number}`);
    printNum(number, delaySec);
    console.log(`Exit  logPrintNum ${number}`);
};

logPrintNum(1, 0);

// 결과
Enter logPrintNum 1
Exit  logPrintNum 1
undefined
1

위와 같은 경우 코드의 순서와 결과가 일치하지 않는 것입니다..

이러한 콜스택에 비었을 때 큐스택에서 하나씩 꺼내어서 다시 이벤트 루프에서 다시 콜스택에 쌓여서 실행되는 문제점을 해결하기 위해

그리고 콜백함수의 지옥을 해결하기 위해 promise가 나오고 이어서 async / await가 나온 것입니다.

 

async 키워드는 항상 함수 앞에 붙고, 항상 promise를 리턴합니다.

 

await는 항상 async 함수 내에서만 사용할 수 있으며, resolve또는 reject를 리턴합니다.

 

그 흐름에 따라서 위의 코드를 고쳐 보면 다음과 같은 결과가 출력됩니다.

let printNum = async (number, delaySec) => {
    await setTimeout(() => console.log(number), delaySec); // i/o 작업을 대신한다.
};

let logPrintNum = async (number, delaySec) => {
    console.log(`Enter logPrintNum ${number}`);
    await printNum(number, delaySec);
    console.log(`Exit  logPrintNum ${number}`);
};

logPrintNum(1, 0);

// 결과
Enter logPrintNum 1
Exit  logPrintNum 1
Promise {<resolved>: undefined}
1

위와 똑같습니다. 달라진게 없습니다.

 

이유는 setTimeOut이 Promise를 리턴하고 하고 있지 않기 때문입니다.

await은 오직 Promise에 대해서만 유효합니다.

 

let printNum = (number, delaySec) => {
    return new Promise((resolve) =>
        setTimeout(() => {
            console.log(number);
            resolve();
        }, delaySec));
};

let logPrintNum = async (number, delaySec) => {
    console.log(`Enter logPrintNum ${number}`);
    await printNum(number, delaySec);
    console.log(`Exit  logPrintNum ${number}`);
};

logPrintNum(1, 0);

// 결과

Enter logPrintNum 1
Promise {<pending>}
1
Exit  logPrintNum 1

이번에는 제대로 나옵니다.

프로미스는 생성자로 콜백함수를 받게 됩니다. 해당 콜백 함수의 첫 번째 인자는 resolve가 됩니다.

resolve가 리턴됨으로 인해서 logPrintNum의 함수내의 await는 resolve가 호출되었음을 알고 그 함수 호출부분으로 다음으로 넘어가게 됩니다.

 

 

map에서의 async / await

map 이나 forEach는 순회함수인데 중간에 async를 만났다고 해서 await가 resolve 또는 reject 리턴을 기다리지 않습니다.

map의 파라미터로 async 함수를 넣어 주면 promise 객체 자체가 리턴되게 됩니다.

 

 

출처 : https://velog.io/@litien/AsyncAwait-%EC%A3%BC%EC%9D%98%ED%95%B4%EC%84%9C-%EB%8B%A4%EB%A3%A8%EA%B8%B0?fbclid=IwAR32EMT_F0aMJI9s3PWGulPx-qugXoLfSyiBmrC12XutCkE2IWgrf7HC0eU

댓글