본문 바로가기
fastcampus

[패스트캠퍼스 수강 후기] 프론트엔드 인강 100% 환급 챌린지 16회차 미션

by 새우하이 2020. 9. 22.

Async - Await

async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다. 그러나 비동기 함수를 사용하는 코드의 구문과 구조는, 표준 동기 함수를 사용하는것과 많이 비슷합니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/async_function

MDN 문서 제목의 async function을 보면 async가 function 앞에붙는 키워드인것을 눈치 챘을 것이다.

async-await 자체가 promise 객체를 기반으로 하고 있다.먼저 Promise 객체를 리턴하는 함수를 정의한다.

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

p(1000).then(ms => {
    console.log(`${ms}ms 후에 실행됩니다.`);
});

앞서 Promise 예제에서는 resolve 가 됐을때 then을 사용해서 비동기가 끝나면 실행되는 작업을 정의했었다.

const ms = await p(1000);
console.log(`${ms}ms 후에 실행됩니다.`);

앞의 코드와 함께 작성되는 예제이다.

이번에는 p(1000)을 실행하는것을 then을 사용하지 않고 await을 사용하면 resolve되었을때 ms가 return값으로 전달 받는다.

따라서 console.log로 ms를 출력할 수 있다.

await을 사용하면 실제로는 비동기적인 처리를 보냈지만 비동기적인 처리가 끝날 때 까지 기다렸다가 resolve 된 후에 resolve될 때 넣어준 인자값을 리턴하여 사용하게 된다.

여기까지 코드를 실행해보면

SyntaxError: await is only valid in async function

이와 같은 에러가 발생하는데 await을 쓰는 표현식이 유효하기 위해서는 async function 내에서 유효하다는 뜻이다. 위의 코드에서는 전역으로 사용중이기 때문에 에러가 난다.

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(ms);
        }, ms)
    });
}
(async function main(){
    const ms = await p(1000);
    console.log(`${ms}ms 후에 실행됩니다.`);
})();

function을 선언과 동시에 바로사용하는 방법으로

( function )(); 의 형태로 사용할 수 있다.

실행하면 1초후에 출력된다.

async가 들어있는 함수가 있을경우 이 함수를 실행하면 내부의 로직이 끝날때까지 프로그램이 종료되지 않고, await을 만나면 비동기처리가 끝날때까지 대기하고 resolve되면 그 값을 리턴 받아 후에 사용되게된다.

Promise 객체가 rejected된 경우의 처리

try catch를 이용

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            //resolve(ms);
            reject(new Error('reason'));
        }, ms)
    });
}
(async function main(){
    try{
    const ms = await p(1000);
    } catch(error){
    console.log(`${error} error`);
    }
})();

catch(error) 에서는 rejected 되었을 때의 인자(new Error)로 만들어진 객체가 error 로 들어오게된다.

에러가 발생되지 않고 정상적으로 실행이 된다면 try{}부분에서 계속 실행이 될 것이다.

지금 까지는 Promise객체를 new키워드를 이용하여 생성하여 리턴하는 function을 사용했었다. 이번에는 async function 자체를 사용하는 방법을 사용해본다.

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            //resolve(ms);
            reject(new Error('reason'));
        }, ms)
    });
}
async function asyncP(){
    return 'jiwon';
} 
(async function main(){
    try{
    const name = await asyncP();
    console.log(name);
    } catch(error){
    console.log(`${error} error`);
    }
})();

async function을 하나 생성하여 문자열을 리턴하고

호출 할때 async function을 바로 또 호출하는데 async function에서 리턴되는 값은 Promise.resolve함수로 감싸서 리턴하게 된다. 그래서 await asyncP() 를 호출하여 name에 담고 name을 출력한다.

이렇게 실행하면 사실 catch까진 가지 않고 resolve만 되며 name을 출력하게 된다.

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(ms);
            //reject(new Error('reason'));
        }, ms)
    });
}
async function asyncP(){
    const ms = await p(1000);
    return 'jiwon'+ms;
} 
(async function main(){
    try{
    const name = await asyncP();
    console.log(name);
    } catch(error){
    console.log(`${error} error`);
    }
})();

main함수에서는 asyncP라는 async function을 await으로 호출 하고 있는데 그럼 await에서는 비동기가 끝날때까지 기다렸다가 밑으로 진행될 것이다.

asyncP에서 await p(1000)을 추가해주면 asyncP가 호출되고 await p(1000)을 만나면 이 p함수를 다시 진행하러 올라가게 된다. p에서 new Promise를 리턴하기 위해 resolve나 reject가 될 때 까지 대기했다가 둘 중 하나가 불릴 때까지 기다렸다가 불리면서 asyncP의 await이 끝나고 다음 순서로 넘어가게 된다.

실행해보면 바로 name이 뜨지 않고 asyncP를 호출하고 asyncP는 p를 통해 얻어온 값을 가지고 다시 return하며 진행이 되기 때문에 1초후에 name이 뜨는것을 볼 수 있다.

이번에는 reject의 결과를 살펴본다

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            //resolve(ms);
            reject(new Error('reason'));
        }, ms)
    });
}
async function asyncP(){
    const ms = await p(1000);
    return 'jiwon'+ms;
} 
(async function main(){
    try{
    const name = await asyncP();
    console.log(name);
    } catch(error){
    console.log(`${error} error`);
    }
})();

이 예제에서는 await p를 하면서 rejected된 결과를 받기 때문에 try catch를 사용하여 await p(1000)의 부분에서 정상적으로 넘길 수 있겠지만 그렇게 하지 않고 실행하게 되면, asyncP 에서 에러가 나는것으로 판단하게되어 main의 catch가 발생하게 된다.

이를 통해서 에러를 컨트롤할 위치를 정할 수 있다.

finally

try catch로 처리가 된 후에 마지막으로 실행될 작업을 정의한다.

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            //resolve(ms);
            reject(new Error('reason'));
        }, ms)
    });
}
async function asyncP(){
    const ms = await p(1000);
    return 'jiwon'+ms;
} 
(async function main(){
    try{
    const name = await asyncP();
    console.log(name);
    } catch(error){
    console.log(`${error} error`);
    } finally{
        console.log('end');
    }
})();

연속된 Promise처리와 async await 처리

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            //resolve(ms);
            reject(new Error('reason'));
        }, ms)
    });
}
p(1000)
.then(() => p(1000))
.then(() => p(1000))
.then(() => {
    console.log('3000ms 후에 실행');
});

//async await
(async function main(){
    await p(1000);
    await p(1000);
    await p(1000);
    console.log('3000ms 후에 실행');
})();

promise의 연속된 비동기처리는 계속 객체를 만들어 return 하여 처리하고

async는 한 줄 한 줄 비동기가 끝나야 진행되는 느낌으로 진행된다.

Promise.all과 Promise.race

function p(ms){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(ms);
            //reject(new Error('reason'));
        }, ms)
    });
}
//promise.all
(async function main() {
    const results = await Promise.all([p(1000), p(2000), p(3000)]);
    console.log(results);
})();

//Promise.race
(async function main2() {
    const results = await Promise.race([p(1000), p(2000), p(3000)]);
    console.log(results);
})();

이전에 Promise.all 과 동일하게 배열 형태로 넘어오게된다.

Promise.race도 마찬가지로 이전과 동일하게 가장 빠르게 처리가 끝난것을 출력하게된다.

해당 내용은 아래 링크에서 수강할 수 있다.

프론트엔드 개발 올인원 패키지 with React Online. 👉https://bit.ly/2ETLEzm

 

프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스

성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.

www.fastcampus.co.kr

 

댓글