본문 바로가기
Study/Express(node.js)

node.js ) 비동기 패턴 해결 (3) - async/await

by JongIk 2022. 2. 5.
반응형

비동기 패턴 해결 - async/await

이전 글에서 Promise 패턴을 이용해 비동기 처리를 동기 처리처럼 처리하는 방법을 다뤘습니다.

 

node.js ) 비동기 패턴 해결 (2) - Promise

비동기 패턴 해결 - Promise 이전 글에서 콜백형태로 비동기 처리하는 방법을 다뤘습니다. 하지만 콜백 형태를 이용해 비동기를 처리하면, 처리는 가능하지만 매우 비효율적으로 코드가 작성됩니

jongik.tistory.com

하지만 async/await 을 이용하면 더 보기 좋은 형태로 비동기를 처리할 수 있습니다.

async/await 구조

async 와 await 는 세트로 사용합니다.

  • test.txt
async test 1
async test 2
const fs = require('fs');

const _p = (val) => {
    return new Promise((resolve, reject) => {
        fs.readFile('./test.txt', (err, data) => {
            if (err) reject(err);
            resolve(`${val} : ${data.toString()}`)
        })
    })
}

async function p() {
    let data1 = await _p(1);
    let data2 = await _p(2);
    let data3 = await _p(3);
    console.log(data1, data2, data3);
}

p();
  • 실행 결과

  • p 함수는 async 키워드를 사용한 함수입니다.
    p 함수에서는 await 키워드를 이용해 Promise 객체인 _p 를 호출합니다.
  • async 과 await 는 _p(1) 에서 호출이 끝날 때까지 기다립니다.
  • 값을 반환하면 그 다음 줄을 실행하고 원하는 한 줄씩 처리되는 형태로 코드로 동작하게 됩니다.

예외처리

async/await 의 예외처리는 매우 간단합니다
try ~ catch 로 에러를 처리할 수 있습니다.

const fs = require('fs');

const _p = (val) => {
    return new Promise((resolve, reject) => {
        fs.readFile('./test.txt', (err, data) => {
            if (err) reject(err);
            reject(`${val} : ${data.toString()}`)
        })
    })
}

async function p() {
    try {
        let data1 = await _p(1);
        let data2 = await _p(2);
        let data3 = await _p(3);
        console.log(data1, data2, data3);
    } catch (err) {
        console.log('err');
        console.log(err);
    }
}

p();
  • 실행 결과

  • Promise 객체에서 reject 가 호출되면 에러로 간주하고 catch 를 실행합니다.
  • async/await 을 이용하면 완전히 동기 처리의 흐름을 실행할 수 있습니다.
    단, await 는 async 와 함께 사용해야 하고 await 을 이용하여 호출하는 대상은 Promise 객체여야 합니다.

async 을 이용해 Promise 객체 만들기

const newMetaPromise = async () => {
    return 'new meta';
};

newMetaPromise().then(res => {
    console.log(res); //'new meta'
})

await 을 이용해 출력하기

const newMetaPromise = async () => {
    return 'new meta';
};

async function another() {
    try {
        let result = await newMetaPromise();
        console.log(result);
    } catch (err) {
        console.log(err);
    }
}

another();
  • 위와 똑같이 동작하는 코드입니다.

Promise.all 처리

function getTime() {
    return new Date().getTime();
}

const a = (t) => {
    return new Promise((resolve, reject) => {
        setInterval(function () {
            resolve(`${t}초 end`)
        }, t * 1000);
    })
}

async function p() {
    let t1 = getTime();
    let d1 = await a(1);
    let t2 = getTime();
    console.log((t2 - t1) / 1000);
    let d2 = await a(2);
    let t3 = getTime();
    console.log((t3 - t2) / 1000);
    let d3 = await a(3);
    let t4 = getTime();
    console.log((t4 - t3) / 1000);
    console.log(d1, d2, d3)
}

p()
  • 실행 결과

  • 위 코드는 원하는 형태로 1초, 2초, 3초 기다리면서 실행합니다.
  • 동시에 처리를 하고 싶을 때는 앞에서 다뤘던 Promise.all 을 이용하면 됩니다.

동시성 처리

function getTime() {
    return new Date().getTime();
}

const a = (t) => {
    return new Promise((resolve, reject) => {
        setInterval(function () {
            resolve(`${t}초 end`)
        }, t * 1000);
    })
}

async function p() {
    let t1 = getTime();
    let d1 = await Promise.all([a(1), a(2)]);
    let t2 = getTime();
    console.log((t2 - t1) / 1000);
    let d3 = await a(3);
    let t3 = getTime();
    console.log((t3 - t2) / 1000);

    console.log(d1,d3)
}

p()
  • 실행 결과

  • 이번에는 1초 처리와 2초 처리를 동시에 실행한 후 3초 처리를 실행하게 됩니다.

정리

3개의 글에서 Promise 와 async/await 을 이용해 비동기 처리를 하는 방법을 다뤘습니다.

Promise 와 async/await 을 잘 조합한다면 더 좋은 구조로 코드를 작성할 수 있습니다.


참고도서 : 자바스크립트로 서버와 클라이언트 구축하기

반응형

댓글