본문 바로가기
Javascript, ES5, ES6

async 와 await 로 작성하는 읽기쉬운 비동기코드 # forEach

by Developer88 2021. 4. 29.
반응형

Javascript에서 비동기를 사용할 때 Promise라는 API를 정리해 보았었는데요.

오늘은 또다른 API인 aysnc와 await에 대해서 정리해 보도록 하겠습니다.

 

이 글은 Promise를 알고 계시는 것이 이해하는데 필요하므로,

Promise에 대해서는 아래 글을 참조해 주세요.

>> Javascript의 Promise를 알아보자 #ES6

 

1. async와 await

promise로 chaining을 해서 잘 사용하고 있었는데, 왜 다른 것이 필요한 것일까요?

async와 await는 비동기코드를 Promise의 Chaining을 하지않고,

좀 더 읽기쉽고 clean한 스타일의 코드로 작성할 수 있도록 도와줍니다.

그러니까, Promise를 좀 더 쉽게 사용할 수있도록 도와주는 API라고 생각할 수 있을 것 같습니다.

 

1-1. Code를 통한 비교 및 이해

코드를 보면서 이해해 보도록 하겠습니다.

먼저, 아래와 같이 Promise객체를 반환하는 myFunc라는 함수가 존재합니다.

 

 

이 함수를 Promise의 Chaining을 붙여서 사용할수도 있구요.

async와 await를 이용할수도 있겠습니다.

 

A. Promise Chaining 방식

먼저 Promise 방식으로 보겠습니다.

"then()" Chaining을 통해서 코드를 작성합니다.

 

 

 

B. Async&Await 방식

이번에는 읽기쉽고 간결해진다는, async와 await를 이용해 보겠습니다.

 

 

매우 간단한 코드이지만, 이 상태만으로도 async와 await를 이용할 이유는 충분히 보이는 것 같습니다.

 

1-2. async 와 await 정리

위에서 코드로 보았던, async와 await를 표로 정리해 보겠습니다.

 

구분 내용
async 이 키워드를 function 앞에 붙이면 await를 사용할 수 있게 됩니다.
또한, resolved 또는 rejected 상태인 Promise객체를 return해 줍니다.

ex> async function myFunc() {}
await async 키워드가 붙은 function 코드 내부에서,
비동기처리 함수앞에 붙여서 사용합니다.

await가 붙은 비동기 함수의 Promise객체의 결과인 resolved 또는 rejected 가 return 될때까지,
처리를 대기하여 줍니다.
결과값이 나오면, 다시 처리를 재개합니다.

ex>
async
function myFunc() {
     const result = await yourFunc();  //비동기함수인 yourFunc()
     console.log(result);
}

 

1-3. Exception 처리

아래와 같이 Exception을 발생시켰다면, 

async와 await방식은 일반적인 try catch 방식과 동일한 방식을 취합니다.

 

 

 

아래는 구글 공식문서에 나오는 코드인데요.

try...catch를 사용하지 않고,

promise에서 사용하는 catch()를 이용해주어도 됩니다.

async와 await를 사용하는 대상은 결국 promise이니까요.

 

 

1-4. Promise.all()에 사용하는 async & await

Promise.all()에도 아래와 같이 async와 await를 사용할 수 있습니다.

 

 

1-5. Babel과 이에 대한 사용

async나 await API는 모든 Browser에서 사용할수는 없는데요.

다만, async와 await를 이용한 코드를 작성한 후에, Babel 모듈을 이용해서 Compile한 후에 사용할 수는 있습니다.

Babel에 관해서는 아래 글을 참조해 주세요.

>> Babel 을 Webstorm 과 터미널 에 적용하는 방법 # Compiler ES6

 

2. forEach 와 비동기 처리

반복문에서 종종 사용되는 forEach를 사용하면 비동기처리에 적합하지 않은 경우가 발생합니다.

await를 사용할 수도 없는데요.

forEach가 비동기처리가 작업을 완료될 때까지 기다려 주지 않기 때문입니다.

forEach 블록안에서는 아래와 같이 await를 쓸수가 없습니다.

 

 

그래서 다음의 2가지 방법을 사용해 주면 되는데요.

특히나 for..of 는 최신 API로서 forEach에서 break도 할 수 있도록 해 줍니다.

  • for 문에 await를 걸어주기
  • for..of 함수 이용하기(ES6의 최신 API)

아래와 같이 for문에 await를 걸어줄 수도 있구요.

 

 

아래와 같이 for..of를 사용해 줄 수도 있습니다.

 

const arr = [1, 2, 3, 4, 5];

async function processData(item) {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(`${item}처리`);
            resolve();
        }, Math.random() * 1000);
    });
}

async function processArray(arr) {
    for (const item of arr) {
        await processData(item);
    }
    console.log('모든 항목 처리 완료');
}

processArray(arr);

 

forEach안에서 꼭 활용해야 한다면, 익명함수의 인자앞에 async 키워드를 붙여주면 됩니다.

이렇게 하면 iteration이 끝나기를 기다리지 않고 비동기로 await함수가 처리가 됩니다.

webstorm 에서 async와 forEach를 사용한다면,

for..of를 쓰는 것을 권장하는데, 아래와 같이 노란색으로 표시가 됩니다.

 

 

728x90

댓글