async 와 await 은 가장 최근에 나온 비동기 처리 패턴으로, 기존의 콜백함수와 프로미스의 단점을 보완한 문법이다.
흔히 말하는 콜백지옥 혹은 여러 개의 프로미스가 서로 의존하고 있는 경우, 코드의 가독성이 저하될 수 있다.
이를 async와 await를 사용하여 더욱 간편하게 가독성있는 코드를 작성할 수 있다.
다음과 같이 프로미스로 작성한 코드를 async를 사용해 간편하게 바꿀 수 있다.
async 함수에서 return은 resolve()와 같은 역할을 한다.
문자열을 반환하는 것처럼 보이지만 실제로는 프로미스를 반환한다.
function promiseFunc() {
return new Promise((resolve, reject) => {
resolve('Promise is awesome')
})
}
promiseFunc().then(console.log)
async function asyncFunc() {
return 'Async is awesome'
}
asyncFunc().then(console.log)
프로미스에서 동기적으로 처리하기 위해 후속 처리 메소드인 then() 메소드를 사용해 동기적으로 처리했다면,
이제는 프로미스를 반환하는 함수 앞에 await을 붙여 더 간편하게 동기적으로 처리할 수 있다.
또한 프로미스를 사용해 동기적으로 처리하는 경우, fullfilled 값을 then() 후속 처리 메소드를 통해 결괏값을 인자로 넘겨 체인 내에서 처리해야 하지만
await을 사용하면 fullfilled 값을 외부로 넘겨줄 수 있다.
다음과 같은 프로미스로 작성한 코드를 async와 await을 사용하여 동기적으로 처리할 수 있다.
const timeout = (value, timeout) => new Promise((resolve, reject) => {
setTimeout(() => resolve(value), timeout)
})
timeout('Hello ', 1000) // 프로그램 실행 후 1초 뒤에 수행
.then(result => {
console.log('complete promise')
return timeout(result + 'My name is ', 2000) // 프로그램 실행 후 3초 뒤에 수행 (1 + 2)
}).then(result => {
console.log('complete promise')
return timeout(result + 'hyun ', 3000) // 프로그램 실행 후 6초 뒤에 수행 (1 + 2 + 3)
}).then(result => {
console.log('complete promise')
console.log(result)
})
complete promise
complete promise
complete promise
Hello My name is hyun
const timeout = (value, timeout) => new Promise((resolve, reject) => {
setTimeout(() => resolve(value), timeout)
})
async function awaitFunc() {
let str = ''
str += await timeout('Hello ', 1000) // 프로그램 실행 후 1초 뒤에 수행
console.log('complete promise')
str += await timeout('My name is ', 2000) // 프로그램 실행 후 3초 뒤에 수행 (1 + 2)
console.log('complete promise')
str += await timeout('hyun ', 3000) // 프로그램 실행 후 6초 뒤에 수행 (1 + 2 + 3)
console.log('complete promise')
return str
}
awaitFunc().then(console.log)
complete promise
complete promise
complete promise
Hello My name is hyun
프로미스에서 예외 처리를 할 때, 후속 처리 메소드인 catch() 메소드를 사용하여 예외 처리를 한다.
async와 await을 사용하면 프로미스를 함수 내부에서 동기적으로 처리할 수 있기 때문에 try-catch 구문을 사용하여 예외 처리를 할 수 있다.
물론 모든 예외를 try-catch 구문으로 처리하는 것은 아니다.
await은 async가 붙은 함수 내에서만 사용 가능하기 때문에, 최종 결과나 처리되지 못한 에러의 경우 catch() 메서드를 사용해 처리해준다.
async function promise() {
throw 'error';
}
promise()
.then(result => console.log('status : fulfilled,', result))
.catch(error => console.log('status : rejected,', error))
status : rejected, error
함수 내부에서 예외가 발생한 경우 try-catch 구문을 이용하여 예외를 처리할 수 있다.
async function promise() {
throw 'rejected';
}
async function exceptionFunc() {
try {
await promise()
} catch (e) {
console.log('catch error!', e)
}
}
exceptionFunc()
catch error! rejected
함수 내부에서 예외가 발생하였지만 예외를 내부가 아닌 외부로 넘겨 처리하고 싶은 경우 다음과 같이 혼용하여 사용할 수 있다.
async function promise() {
throw 'rejected';
}
async function exceptionFunc() {
try {
return await promise()
} catch (e) {
console.log('catch error!', e)
throw e
}
}
exceptionFunc()
.then(result => console.log('status : fulfilled,', result))
.catch(error => console.log('status : rejected,', error))
catch error! rejected
status : rejected, rejected