![Typescript 이해하기 - Async/Await 이해하기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtuLXh%2FbtsA3ZxlfWI%2FK7zLye4ZuVuMe6VLQ1RDJk%2Fimg.png)
2023.11.28 - [백엔드/Typescript] - Typescript 이해하기 - 제너레이터 이해하기
2023.11.27 - [백엔드/Typescript] - Typescript 이해하기 - Promise 이해하기
필요 배경 지식
- TypeScript Promise 개념 이해
- TypeScript Generator 개념 이해
Prerequisite
- TypeScript 컴파일 환경 구축
Async/Await
Async와 Await의 기본적인 규칙은 다음과 같다.
1. async 는 항상 await 과 항상 같이 사용된다.
2. await은 async function 안에서만 사용된다.
3. function 앞에 async를 붙이면 해당 함수는 항상 Promise를 Return 한다. Promise가 아닌 값을 반환하더라도 resolved Promise로 값을 감싸서 이를 반환 하도록 한다.
Async
예제는 아래와 같다.
async function f() {
return 1;
}
f().then(alert); // 1
명시적으로 Promise를 반환해도 결과는 동일하다.
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
Await
Await은 Async 함수 안에서만 사용이 가능하다.
또한, 자바스크립트는 await 키워드를 만나면 Promise가 처리 될 때 까지 기다린다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
f();
await은 말 그대로 Promise가 처리 될 때 까지 함수 실행을 기다리게 한다.
Promise가 처리 되면 그 결과와 함께 실행이 재개된다.
Promise가 처리 되길 기다리는 동안 프로그램이 다른 일들을 처리할 수 있어서 CPU 리소스가 낭비되지 않는다.
따라서, await은 promise.then 보다 조금 더 세련되게 Promise의 result 값을 얻을 수 있게 해주는 문법이다.
에러 핸들링
Promise가 정상적으로 이행되면 await Promise는 Promise 객체의 result에 저장된 값을 반환한다.
반면, Promise가 rejected 되면 마치 throw 문을 작성한 것 처럼 에러가 던져진다.
async function f() {
await Promise.reject(new Error("에러 발생!"));
}
//위와 아래는 동일한 코드이다.
async function f() {
throw new Error("에러 발생!");
}
그리고 await가 던진 에러는 throw가 던진 에러를 잡을때 처럼 try..catch 문을 이용해 잡을 수 있다.
async function f() {
try {
let response = await fetch('http://유효하지-않은-주소');
} catch(err) {
alert(err); // TypeError: failed to fetch
}
}
f();
async function f() {
try {
let response = await fetch('http://유효하지-않은-주소');
let user = await response.json();
} catch(err) {
// fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
alert(err);
}
}
f();
try..catch가 없으면 아래의 예시처럼 async 함수 f()를 호출해 만든 Promise가 rejected 된다.
f()에 .catch()를 추가하면 rejected 된 Promise를 처리할 수 있다.
async function f() {
let response = await fetch('http://유효하지-않은-주소');
}
// f()는 거부 상태의 프라미스가 됩니다.
f().catch(alert); // TypeError: failed to fetch // (*)
.catch()를 추가하지 않으면 처리 되지 않은 Promise 에러가 발생한다.
async/await과 Promise.then/catch
async/await을 사용하면 await가 대기를 처리해주기 때문에 .then이 거의 필요하지 않다. 여기에 더하여 .catch 대신 일반 try..catch를 사용할 수 있다는 장점도 있다. 항상 그러한 것은 아니지만, promise.then을 사용하는 것보다 async/await를 사용하는 것이 대개는 더 편리하다.
그런데 문법 제약 때문에 async함수 바깥의 최상위 레벨 코드에선 await를 사용할 수 없다. 그렇기 때문에 관행처럼 .then/catch를 추가해 최종 결과나 처리되지 못한 에러를 다룬다. 위 예시의 (*)로 표시한 줄처럼.
async/await은 promise.all과도 같이 쓸 수 있다.
여러개의 Promise가 모두 처리되어야 하는 상황이면 이 Promise들을 Promise.all로 감싸고 여기에 await을 붙여 사용할 수 있다.
// 프라미스 처리 결과가 담긴 배열을 기다립니다. let results = await Promise.all([ fetch(url1), fetch(url2), ... ]);
요약
function 앞에 async를 추가하면 두가지 효과가 있다.
1. 함수는 언제나 Promise를 반환한다.
2. 함수안에서 await을 사용할 수 있다.
Promise 앞에 await을 붙이면 JavaScript는 Promise가 처리될 때 까지 기다린다.
처리가 완료되면 조건에 따라 아래와 같은 동작이 이어진다.
1. 에러발생 - 예외가 생성됨 ( 에러가 발생한 장소에서 throw error를 호출한것과 동일)
2. 에러 미발생 - Promise 객체의 result 값을 반환
Reference
Async Await - TypeScript Deep Dive
wrapToReturnPromise는 제네레이터 함수를 사용하여 generator 객체를 반환받은 다음, generator.next()를 사용합니다. 만약 값이 promise 라면 then+catch하고 결과값을 generator.next(result)또는 generator.thorw(error) 로
radlohead.gitbook.io
async와 await
ko.javascript.info
'백엔드 > NodeJS | Typescript' 카테고리의 다른 글
Typescript - TypeORM 사용해서 DB 쿼리하기 (0) | 2023.12.13 |
---|---|
Typescript 프로젝트의 naming convention (0) | 2023.12.07 |
Typescript 이해하기 - 제너레이터 이해하기 (0) | 2023.11.28 |
Typescript 이해하기 - Promise 이해하기 (0) | 2023.11.27 |
Typescript 변수 타입 (0) | 2023.11.26 |
개발 및 IT 관련 포스팅을 작성 하는 블로그입니다.
IT 기술 및 개인 개발에 대한 내용을 작성하는 블로그입니다. 많은 분들과 소통하며 의견을 나누고 싶습니다.