async와 await은 자바스크립트의 비동기 처리 패턴인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 도와주는 비동기 처리방식입니다.
async는 function 앞에 붙게 됩니다.
async function foo(){
return 123;
}
async가 붙은 해당 함수는 항상 Promise 객체를 반환하게 됩니다. Promise 객체가 아닌 값을 반환하게 되더라도 이행 상태(fulfilled)의 Promise(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 합니다.
아래 예시의 함수를 호출하게 되면 result 값이 1인 이행 상태의 Promise가 반환됩니다.
async function foo() {
return 123;
}
f().then(alert); // 123
명시적으로 프라미스를 반환하는것 또한 가능한데 결과는 동일하게 나옵니다.
async function f() {
return Promise.resolve(123);
}
f().then(alert); // 123
await 문법은 async 함수 안에서만 작동이 됩니다.
async function foo() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
const result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
foo();
자바스크립트는 await 키워드를 만나게 되면 Promise 처리가 될 때까지 기다립니다. 결과는 그 이후에 반환됩니다.
함수를 호출하고 , 함수 본문이 실행되는 도중이 (*)로 표시한 줄에서 실행이 잠시 '중단'되었다가 Promise가 처리되면 실행이 재개됩니다. 이때 프라미스 객체의 result 값이 변수 result에 할당됩니다. 따라서 위 예시를 실행 하면 1초 뒤에 '완료!'가 출력이 됩니다.
await은 말 그대로 Promise가 처리 될 때까지 함수 실행을 기다리게 만듭니다. Promise가 처리되면 그 결과와 함께 실행이 재개되죠. Promise가 처리 되길 기다리는 동안엔 엔진이 다른일(다른 스크립트를 실행하거나 이벤트 처리하는 등) 을 할 수 있기에 CPU 리소스가 낭비되지 않습니다.
** 일반 함수에는 await을 사용 할 수 없습니다 !!**
function foo(){
let promise = promise.resolve(1);
let result = await promise; // Syntax error
}
async 와 await을 사용하면 Promise 체이닝을 사용하는것보다 훨씬 깔끔하게 됩니다.
await은 최상위 레벨 코드에서 작동하지 않습니다.
// 최상위 레벨 코드에선 문법 에러가 발생함
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();
...
})();
Promise가 정상적으로 이행되면 await promise는 프라미스 객체의 result에 저장된 값을 반환합니다. 반면 Promise가 거부되면 마치 throw문을 작성한 것처럼 에러가 던져집니다.
async function foo() {
await Promise.reject(new Error("에러 발생!"));
}
위 코드는 아래 코드와 동일합니다 !
async function foo() {
throw new Error("에러 발생!");
}
await 에러처리는 try , catch를 이용한 방법도 있습니다.
async function foo() {
try {
let response = await fetch('http://유효하지-않은-주소');
} catch(err) {
alert(err); // TypeError: failed to fetch
}
}
foo();
에러가 발생하면 제어 흐름이 catch 블록으로 넘어가게 됩니다.
또는 함수 내부에 없이 외부에서 부를 때 catch를 이용하여 에러처리를 할 수 있습니다
async function foo() {
let response = await fetch('http://유효하지-않은-주소');
}
// foo()는 거부 상태의 프라미스가 됩니다.
foo().catch(alert); // TypeError: failed to fetch // (*)
출처 : ko.javascirpt.info