위 글에서 언급은 했지만, 자바스크립트는 싱글 스레드로 비동기 작업을 처리해 주는 작업이 필요하다
비동기 작업을 처리해 주는 객체이자 패턴 중 하나는 Promise이며 이와 유사하게 async와 await도 있다
async, await
마찬가지로 비동기 처리 패턴 중 하나로 동기 처리처럼 동작하도록 구현할 수 있다.
ES8에서 나온 문법으로서 비동기 코드를 더 읽기 쉽게 작성하도록 도와주는 역할을 한다.
async 키워드를 사용한 함수는 Promise를 반환하기에 then, catch, finally 메서드도 연달아 쓸 수 있는 메서드 체이닝이 가능하다.
await 키워드는 프로미스가 settled 상태가 될 때까지 대기를 하다가 settled 상태가 되면 프로미스가 resolve한 결과를 처리한다. 반드시 async 함수 내부에서 사용해야 하며 반드시 프로미스 앞에서 사용해야 한다. await 뒤에 프로미스가 아닌 다른 값이 와도 되지만 코드에 아무런 영향도 미치지 않아서 await를 쓴 효과가 없다.
try-catch 구문으로 async/await 형태의 비동기 코드 에러 처리도 가능하다
async function runAsyncAwait() {
try {
let user = await getUser(1);
console.log(user);
let post = await getPost(user.id);
console.log(post);
let comments = await getComments(post[0].id);
console.log(comments);
return {user, post, comments};
} catch(err) {
console.log(err)
}
}
Promise를 async함수로 변경하기
1. 함수에 async 키워드 작성
2. new Promise 부분을 없애고 함수의 본문 내용만 남겨둠
3. resolve(value)를 return value로 바꿔줌
4. reject는 throw로 수정 -> 에러 처리
then, catch문을 await로 변경하기
1. then, catch문에서 하는 작업을 async func으로 감싸줌
2. async func의 error 처리를 try-catch 문으로 작성
3. async func에 await문 작성
4. 감싼 async func 호출
비동기 패턴의 발전 과정
1) 콜백함수 -> 2) Promise -> 3) async/await
그렇다면, Promise가 async/await를 완전히 대체할 수 있을까?
setTimeout에서 resolve는 콜백함수로서 넘어가 task queue로 넘겨주지만, async에서는 return 값으로 넘어가고 콜백함수가 없다. 즉, setTimeout가 끝났을 때 호출하는 콜백함수가 없어서 async로 컨트롤할 수 없기 때문에 Promise가 필요하다.
=> 완전히 대체 불가능
동시 실행
1. Promise + async
동시 실행을 위해서는 Promise와 async를 같이 써줄 수 있다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(2000);
return "apple";
}
async function getBanana() {
await delay(1000);
return "banana";
}
// async만 사용
async function fruit() {
const apple = await getApple();
const banana = await getBanana();
console.log(`${apple} + ${banana}`);
}
fruit();
// 3초 걸림
// promise + async를 같이
async function fruit() {
const [a, b] = await Promise.all([getApple(), getBanana()]);
console.log(`${a} + ${b}`);
}
fruit();
// 2초 걸림
2. only async
async만으로 동시 실행을 진행시켜줄 수 있다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(2000);
return "apple";
}
async function getBanana() {
await delay(1000);
return "banana";
}
async function fruit() {
const promiseapple = getApple(); // pending 상태인 프로미스 자체가 찍히는 것
// JS엔진 입장에서는 0초 이후 바로 아래 코드 실행
const promisebanana = getBanana();
const apple = await promiseapple;
const banana = await promisebanana;
console.log(`${apple} + ${banana}`);
}
fruit();
'IT Study > JavaScript' 카테고리의 다른 글
[NestJS] Repository Pattern (0) | 2024.01.07 |
---|---|
[NestJS] 게시글 DB에 저장하기 (with PostgreSQL) (0) | 2024.01.04 |
[JS] setTimeout의 clearTimeout, 디바운싱, 쓰로틀링 (0) | 2023.09.06 |
[JavaScript] 핵심 개념(1) 동기·비동기 | 이벤트 루프 | Promise (0) | 2023.09.04 |
[JS] 제곱 리스트를 찾는 방법(filter, map, reduce, every) (0) | 2023.09.01 |