JavaScript/ES6+

ES6+ | Async Await

pathas 2020. 5. 18. 14:42

Async Await

async await은 비동기 프로그래밍을 동기 프로그래밍처럼 작성할 수 있도록 함수에 추가된 기능

  • ES2017에 자바스크립트 표준으로 등록
  • 프로미스의 then 메서드를 체인 형식으로 호출하는 것보다 가독성이 좋음
  • 프로미스는 비동기 상태를 값으로 다룰 수 있는 async await 보다 큰 개념으로,
    async await이 프로미스를 완전히 대체할 수는 없음

async await 이해

async await 함수는 프로미스를 반환

프로미스는 객체로 존재하지만 async await은 함수에 적용되는 개념

async function getData() {
    return 123;
}
getData().then(data => console.log(data));
// 123
// Promise {<resolved>: undefined}

async function getData() {
    return Promise.resolve(123);
}
getData().then(data => console.log(data));
// 위의 함수와 동치

async function getData() {
    throw new Error('123');
}
getData().catch(error => console.log(error));
// Error: 123
  • async 키워드로 정의된 함수는 async await 함수이며, 항상 프로미스를 반환
  • 프로미스를 반환하기 때문에 then 메서드 사용 가능
  • async await 함수 내부에서 프로미스를 반환하면 그 객체를 그대로 반환
  • async await 함수 내부에서 예외가 발생하는 경우, 거부됨 상태의 프로미스 반환

await 키워드 사용법

  • await 키워드는 async await 함수 내부에서 사용
  • await 키워드 오른쪽에 프로미스를 입력하면 그 프로미스가 처리됨 상태가 될 때까지 기다림
  • 즉 await 키워드로 비동기 처리를 기다리면서 순차적으로 코드 작성 가능
  • await 키워드는 오직 async await 함수 내에서만 사용 가능
    → 일반 함수에서 사용 시 에러 발생

async await 사용례

function requestData(value) {
    return new Promise(resolve =>
        setTimeout(() => {
            console.log('requestData:', value);
            resolve(value);
        }, 1000),
    );
}
async function getData() {
    const data1 = await requestData(10);
    const data2 = await requestData(20);
    console.log(data1, data2);
    return [data1, data2];
}
getData();
// requestData: 10
// requestData: 20
// 10 20
  • requestData 함수가 반환하는 프로미스가 처리됨 상태가 될 때까지 getData 함수 내부의 console.log()는 실행되지 않음

async await 활용

비동기 함수 병렬 실행

// 순차적 실행
async function getData() {
    const data1 = await awaitFunc1();
    const data2 = await awaitFunc2();
    // ...
}

// 병렬 실행
async function getData() {
    const p1 = awaitFunc1();
    const p2 = awaitFunc2();
    const data1 = await p1;
    const data2 = await p2;
    // ...
}

// Promise.all
async function getData() {
    const [data1, data2] = await Promise.all([asyncFunc1(), asynFunc2()]);
}
  • 두 개 이상의 비동기 함수가 실행될 때 서로 의존성이 없다면 동시에 실행하는 것이 좋음
  • 프로미스는 생성과 동시에 비동기 코드가 실행됨 즉, 프로미스를 먼저 생성하고 await 키워드를 나중에 사용하면 병렬로 실행됨
  • 위에서는 두 개의 프로미스가 생성된 후 기다리기 때문에 두 개의 비동기 함수가 병렬로 처리됨
  • Promise.all 을 사용할 수도 있음

예외 처리

async await 함수 내부에서 발생하는 예외는 try catch 문으로 처리하는 게 좋음

async function getData() {
    try {
        await doAsync(); // 비동기 함수
        return doSync(); // 동기 함수
    } catch(error) {
        console.log(error);
    }
}
  • 비동기 함수와 동기 함수에서 발생하는 모든 예외는 catch 문에서 처리
  • getData 함수가 async await 함수가 아니었다면 doAsync 함수에서 발생하는 예외는 catch 문에서 처리되지 않음
    ∵ doAsync 함수의 처리가 끝나는 시점을 알 수 없음

참고도서: [ 실전 리액트 프로그래밍 / 저자_ 이재승 / 출판사_ 프로그래밍 인사이트 ]