async, await는 비동기 함수를 표준 동기 함수를 사용하는 것처럼 간단하게 쓸 수 있게 해 준다.
어떤 함수 앞에 async
키워드를 붙이면, 해당 함수는 항상 Promise를 반환한다. 혹은, Promise가 아니더라도 이행 상태(resolved)의 promise로 값을 감싸, resolved promise가 반환되도록 한다.
await는, 앞서 정의한 async 함수를 실행할 때만 사용 가능하다.
자바스크립트는 await 키워드를 만나면, Promise가 처리될 때까지 실행을 중단한다. 그리고 결과는 Promise가 처리된 실행을 재개한다.
async 함수의 본문은 await가 포함되어야만 비동기적으로 실행된다. 만약 async 함수가 await 없이 실행된다면, 동기적으로 실행된다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // Promise가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
f();
위 예시에서 f() 함수의 본문은 중간에 await promise;
로 된 구간에서 실행이 잠시 중단되었다가, promise가 처리되면 실행이 재개된다. 이때, 변수 let result에는 Promise 객체인 promise의 결괏값이 할당된다.
이때, 프라미스가 처리되는 동안에는 엔진은 다른 스크립트를 실행하거나, 이벤트 처리를 할 수 있기 때문에 CPU 리소스가 낭비되지 않는다.
await
는 promise.then
보다 가독성 좋고 쓰기 쉬운 코드로 결괏값을 얻을 수 있게 해 주는 문법이다.
await는 최상위 레벨 코드에서는 작동하지 않는다. 하지만, 익명 async 함수로 감싸면 최상위 레벨에서도 사용 가능하다.
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
------------------------------------
/* 하지만, 익명 async 함수로 감싸면 최상위 레벨에서도 사용 가능! */
(async () => {
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
...
})();
throw
문을 작성한 것처럼 예외가 생성되는 형태로 에러가 던져진다.async function f() {
await Promise.reject(new Error("에러 발생!"));
}
---------
/* 위 코드는 아래와 동일하다. */
async function f() {
throw new Error("에러 발생!");
}
throw
를 활용해 에러를 발생시키고, await promise의 에러는 throw
가 던진 에러를 잡을 때처럼 try...catch
를 사용해 잡는다.async function f() {
try {
let response = await fetch('http://unavailable-url');
let user = await response.json();
} catch(err) {
// fetch와 response.json에서 발행한 에러 모두를 여기서 잡음.
alert(err);
}
}
f();
async 함수 내부에서 try...catch
로 적절히 에러를 제어해 주지 않는다면, async 함수를 호출해 만든 Promise는 거부(rejected) 상태가 된다.
이럴 경우, .then()
, .catch()
를 사용하면 거부된 Promise를 처리할 수 있다.
async function f() {
let response = await fetch('http://unavailable-url');
}
// f()는 거부 상태의 프라미스가 된다. .catch를 사용해 처리한다.
f().catch(alert); // TypeError: failed to fetch
Promise 처리 결과가 담긴 배열을 기다린다.
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]); // 등록된 모든 프로미스가 성공해야 results가 성공한 것으로 간주된다.
출처