async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다. 그러나 비동기 함수를 사용하는 코드의 구문과 구조는, 표준 동기 함수를 사용하는것과 많이 비슷합니다. - MDN 공식 문서
자바스크립트를 이용한 비동기 처리 시 Promise만을 이용한 방식을 이용할 수 있지만 ES8(ECMA2017)에서 추가된 async await을 이용하면 좀더 비동기 코드의 겉모습과 동작을 좀 더 동기 코드와 유사하게 만들어주기때문에 가독성이 좋은 코드를 작성할 수 있다.
async function 함수이름() {
await 비동기_메서드();
};
const 함수이름 = async(){
await 비동기_메서드();
}
함수 앞에 async라는 예약어를 붙인뒤 비동기 메서드 앞에 await을 붙이면 된다. 쉽게 말하자면 await의 의미는 "뒤에 붙은 비동기 메서드의 프라미스가 처리(settled) 될때까지 기다려!" 라는 의미이다. 또한 async await은 Promise를 이용한 비동기 처리에 기반을 두고있기 때문에 비동기 처리 메서드가 Promise 객체를 반환해야 await이 의도한데로 동작한다.
function test(ms){
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(ms);
}, ms)
});
}
// Promise 객체를 이용한 비동기 처리
test(1000).then(ms => {
console.log(`${ms}ms 후에 실행.`);
})
// 1000ms 후에 실행.
// Promise 객체를 리턴하는 함수를 await으로 호출하는법.
(asyncTest = async()=>{ // 즉시 실행 함수
const ms = await test(1000);
console.log(`${ms}ms 후에 실행.`);
})();
// 1000ms 후에 실행.
Promise 객체를 리턴하는 test라는 함수를 만들어준뒤 Promise, async await을 이용해 각각 비동기 처리를 어떻게 처리하는지에 대한 간단한 예제이다. 예제 내의 async 함수안의 ms는 await 처리 때문에 test 함수에서 1000ms 뒤에 resolve로 1000을 넘길때까지 기다린뒤에 할당이 이루어 지게된다.
async 함수 내부에서 값을 리턴 시키면, 자바스크립트는 그 값을 Promise의 이행값으로 만든다. Promise가 아닌 값을 반환 하더라도 자바스크립트는 이를 처리가 끝난 Promise로 값으로 반환되게 한다.
async function asyncReturnPromise() {
return "Hello";
}
asyncReturnPromise().then(function(result){
console.log(result)
}) // Hello
function test(ms){
return new Promise((resolve, reject) => {
setTimeout(()=>{
reject(new Error('just error'))
}, ms)
});
}
// Promise 객체를 리턴하는 함수를 await으로 호출하는법.
(asyncTest = async()=>{
try{
const ms = await test(1000);
} catch (error){
console.log(error)
};
})();
// :Error: just error
위와 같은 예제에서 이번에는 test함수에서 reject 를 통해 에러를 발생시킨뒤 asyncTest에서 에러 처리를 해주었다. Promise의 에러 처리처럼 try, catch로 감싸주면 된다. 즉 reject에서 발생시킨 에러는 아래의 catch구문의 인자로 전달되어 정상적으로 에러출력을 하게된다.
const arr = ['a','b','c','d'];
function print (i,time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(i);
console.log(i);
}, 1000)
});
}
async function start(arr){
let count = 1;
let done;
for(item of arr){
done = await printArr(item, count);
count++
}
return done;
}
start(arr).then( result => console.log(`${result}를 마지막으로 종료되었습니다.`))
/*
a
b
c
d
d를 마지막으로 종료되었습니다.*/
만일 배열의 값들을 순차적으로 Promise를 리턴해주는 print()에 넣어서 병렬적 처리가 아닌 직렬적 처리 하고싶다면 for of 문을 이용하여 배열의 요소가 하나씩 차례대로 처리되고 마지막 결과값도 출력할 수 있다.