지난시간에 알아봤던 비동기, 콜백, Promise에 이어 async await도 알아보겠습니다. 비동기를 처리하는 여러가지 방법 중 하나인데 프로미스와도 연관되는 부분이 많아 함께 공부하면 좋을 것 같네요. 오늘도 제 나름대로 배운 부분을 정리해보겠습니다.
async function 선언을 통해 비동기 함수를 정의할 수 있고, 이렇게 정의한 비동기 함수를 사용할 때는 표준 동기함수를 사용하는 것과 비슷하게 쓸 수 있다.
Promise에 .then()을 사용하던 방식을, 조금 더 보기 편하게 일반 함수처럼 쓸 수 있게 된다. 내부적으로 Promise를 사용하므로 전혀 다른 방법이라기보단 하나의 새로운 편리한 사용법이라고 생각하면 좋을 것 같다.
우선 async에 대해 알아보자.
function 앞에 async 키워드를 사용하면 해당 함수는 항상 프라미스를 반환하게 된다. Promise와 then에서와 비슷하게 프라미스가 아닌 값을 반환하면 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되게 된다.
async function f() {
return 1;
}
f().then(alert); // 1
와
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
는 같은 결과를 보여준다.
이렇게 async 함수를 만들게 되면, 이 함수 안에는 await이라는 키워드를 사용 할 수 있게 된다.
await은 단어 그대로 기다린다는 의미인데, await 키워드는 프라미스(또는 thenable 객체)가 처리(settled)될 때까지 기다린다. 그 이후 결과가 반환된다.
어딘가엔 promise.then보다 조금 더 가독성이 좋게 result값을 얻을 수 있는 문법
이라고 설명되어 있다. 상황에 따라 프라미스를 조금 더 보기쉽게 표현 할 수 있겠다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
f();
위 코드를 실행해보면 1초 후에 '완료!'라는 문구가 출력될것이다.
함수가 호출되어 실행될 때 await이 포함되어있는 줄에서 실행이 중단되었다가, 프라미스가 처리된 후 실행이 재개된다.
- async로는 내가 처리할 비동기 동작을 async 키워드를 사용한 함수로 만들고 그 안에서는 await 키워드를 사용 할 수 있다. 반환값은 항상 프라미스이다.
- async 함수 내부에서 프라미스들의 결과를 await을 통해서 반환될때까지 기다렸다가 실행한다. 그리고 그 함수의 반환값은 항상 프라미스가 된다.
await
은 thenable 객체
를 받는다. 그래서 객체가 .then을 지원하면 이 객체를 await
과 함께 사용할 수 있다.thenable 객체란 then 메서드가 있는 호출 가능한 객체로, 서드파티 객체가 프라미스가 아니지만 프라미스와 호환 가능한 객체를 제공 할 수 있다는 점에서 생긴 기능이라고 한다.
예를 들어
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve);
// 1000밀리초 후에 이행됨(result는 this.num*2)
setTimeout(() => resolve(this.num * 2), 1000); // (*)
}
};
async function f() {
// 1초 후, 변수 result는 2가 됨
let result = await new Thenable(1);
alert(result);
}
f();
이렇게도 사용할 수 있는것이다.
클래스 메서드로도 async를 사용할 수 있다.
에러 핸들링
프라미스가 정상적으로 이행되면 await promise 구문은 프라미스 객체의 result값을 반환한다. 하지만 거부되면 throw문을 사용 한 것처럼 에러가 던져진다.
이를 try..catch를 사용해 잡을 수 있다.
만약 try..catch가 없으면 프라미스가 거부 상태가 되며 .catch를 추가하여 거부된 프라미스를 처리할 수도 있다.
-MDN-async function
-javascript.info - async await
개인적으로 MDN의 설명과 예제는 난이도가 있었고 javascript.info의 설명은 조금더 친절하게 설명해주는 느낌이니 참고해주면 좋을것같다.