LHJ

I'm a FE developer.

2.1.7 async/await

01 Aug 2020 » node_book

2.1.7 async/await

노드 7.6 버전부터 지원되는 기능입니다.
자바스크립트 스팩은 ES2017입니다.
최신 기능이면서 정말 혁신적인 기능입니다.
특히 노드처럼 비동기 프로그래밍을 해야할 때 도움이 많이 됩니다.
프로미스가 콜백 지옥을 해결했다지만, 여전히 코드가 장황합니다.
async/await 문법은 프로미스를 사용한 코드를 한 번 더 깔끔하게 줄여줍니다.

2.1.6 절의 프로미스 코드를 다시 한 번 보겠습니다.

function findAndSaveUser(Users) {
    Users.findOne({})
        .then((user) => {
            user.name = 'zero';
            return user.save();
        })
        .then((user) => {
            return Users.findOne({ gender: 'm' });
        })
        .then((user) => {
            // 생략
        })
        .catch(err => {
            console.error(err);
        });
}

콜백과 다르게 코드의 깊이가 깊진 않지만, 코드 길이는 여전히 깁니다.
async/await 문법을 사용하면 다음과 같이 바꿀 수 있습니다.
async function이라는 것이 추가되었습니다.

async function findAndSaveUser(Users) {
    let user = await Users.findOne({});
    user.name = 'zero';
    user = await user.save();
    user = await Users.findOne({ gender: 'm' });
    // 생략
}

놀라울 정도로 코드가 짧아졌습니다.
함수 선언부를 일반 함수 대신 async function으로 교체한 후, 프로미스 앞에 await를 붙여주었습니다.
이제 함수는 해당 프로미스가 resolve될 때까지 기다린 뒤 다음 로직으로 넘어갑니다.
예를 들면 await Users.findOne({})resolve될 때까지 기다린 뒤, user 변수를 초기화하는 것입니다.

위 코드는 에러를 처리하는 부분이 없으므로 다음과 같은 추가 작업이 필요합니다.

async function findAndSaveUser(Users) {
    try {
        let user = await Users.findOne({});
        user.name = 'zero';
        user = await user.save();
        user = await Users.findOne({ gender: 'm' });
        // 생략
    } catch (error) {
        console.error(error);
    }
}

try/catch문으로 로직을 감쌌습니다.
프로미스의 catch 메서드처럼 try/catch문의 catch가 에러를 처리합니다.

화살표 함수도 async와 같이 사용할 수 있습니다.

const findAndSaveUser = async (Users) => {
    try {
        let user = await Users.findOne({});
        user.name = 'zero';
        user = await user.save();
        user = await Users.findOne({ gender: 'm' });
        // 생략
    } catch (error) {
        console.error(error);
    }
}

for문과 async/await을 같이 써서 Promise.all을 대체할 수도 있습니다.
이것은 노드 10 버전부터 지원하는 ES2018 문법입니다.

const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');
(async () => {
    for await (promise of [promise1, promise2]) {
        console.log(promise);
    }
})();

Promise.all 대신 for await of문을 사용해서 프로미스를 반복하는 모습입니다.

앞으로 중첩되는 콜백 함수가 있다면 프로미스를 거쳐 async/await 문법으로 바꾸는 연습을 해보기 바랍니다.
코드가 훨씬 간결해질 것입니다.
이 책의 예제는 async/await 문법을 적극적으로 사용하므로 익숙해지는 것이 중요합니다.

이외에도 많은 문법이 추가되었습니다.
하지만 이 책에서는 위에서 설명한 내용 정도만 자주 사용합니다.
다른 변경 사항이 궁금한 분들을 위해 이 장 끝부분에 새로운 문법을 배울 수 있는 사이트의 링크를 적어놓았습니다.

이제 프론트앤드에서 사용되는 자바스크립트 코드를 알아보겠습니다.