[JS] async와 await

Jiwon Youn·2021년 2월 19일
0

async

function 앞에 async를 붙이면 해당 함수는 항상 promise를 반환한다. promise가 아닌 값을 반환하더라도 이행 상태의 promise로 값을 감싸 이행된 promise가 반환되도록 한다.

아래 예시의 함수를 호출하면 result1인 이행 promise가 반환된다.

async function f() {
 return 1;
}

f().then(alert); // 1

await

자바스크립트는 await 키워드를 만나면 promise가 처리(settled) 될 때까지 기다린다. 결과는 그 이후 반환된다.

async function f() {
 let promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("complete"), 1000)
 });
 
 let result = await promise; // promise가 이행될 때까지 기다림
 
 alert(result); // "complete"
}

f();

1초 후 이행되는 promise를 예시로 사용하여 await 실행
함수를 호출하고, 함수 본문이 실행되는 도중에 await문에서 잠시 실행이 중단되었다가 promise가 처리되면 실행이 재개된다. 이 때 promise 객체의 result 값이 변수 result에 할당된다.

async 함수가 아닌데 await을 사용하면 문법 에러가 발생한다.


Error Handling

await가 던진 에러는 throw가 던진 에러를 잡을 때처럼 try..catch를 이용해 잡을 수 있다.

async function f() {
 try {
  let response = await fetch('http://유효하지-않은-주소');
 } catch(err) {
  alert(err); // TypeError : failed to fetch
 }
}

f();

에러가 발생하면 제어 흐름이 catch 블록으로 넘어간다.

try..catch가 없으면 아래 예시의 async함수 f()를 호출해 만든 promise 거부 상태가 된다. f().catch를 추가하면 거부된 promise를 처리할 수 있다.

async function f() {
 let response = await fetch('http://유효하지-않은-url');
}

// f()는 거부 상태의 promise가 된다.
f().catch(alert); 

.catch를 추가하는 걸 잊으면 처리되지 않은 promise 에러가 발생한다. 이런 에러는 전역 이벤트 핸들러 unhandledrejection을 사용해 잡을 수 있다.

문법 제약 때문에 async 함수 바깥의 최상위 레벨 코드에선 await 함수를 사용할 수 없다. 그렇기 때문에 관행처럼 .then/catch를 추가해 최종 결과나 처리되지 못한 에러를 다룬다.


async/await with Promise.all

여러 개의 promiser가 모두 처리되길 기다려야 하는 상황이라면 이 promise들을 Promise.all로 감싸고 여기에 await을 붙여 사용할 수 있다.

let results = await Promise.all([
 fetch(url1),
 fetch(url2),
 ...
]);

실패한 promise에서 발생한 에러는 보통 에러와 마찬가지로 Promise.all로 전파된다. 에러 때문에 생긴 예외는 try..catch로 감싸 잡을 수 있다.

참고 출처 : https://ko.javascript.info/async

0개의 댓글