async
키워드는 함수 선언시에 앞에 붙여준다.
promise
밀접한 연관이 있는데 아래 코드에서 new Promise
를 리턴하는 함수를 async
함수로 바꿔보자
// 기존
// function startAsync(age) {
// return new Promise((resolve, reject) => {
// if (age > 20) resolve(`${age} success`);
// else reject(new Error("Something went wrong"));
// });
// }
async function startAsync(age) {
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
}
setTimeout(() => {
const promise1 = startAsync(25);
promise1
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
const promise2 = startAsync(15);
promise2
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
}, 1000);
25 success
Error: 15 is not over 20
at startAsync (/home/taehoon/Desktop/playground-nodejs/index.js:11:14)
at Timeout._onTimeout (/home/taehoon/Desktop/playground-nodejs/index.js:23:20)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
이전 Promise 챕터의 코드와 완벽하게 같은 결과를 보여준다(내부적으로 다를 순 있지만)
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
코드 자체만 보면 문자열이 리턴될 것으로 예상할 수 있지만
async function startAsync(age) {
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
}
const promise1 = startAsync(15)
console.log(typeof promise1); // object
console.dir(promise1) // Promise
짠! async
키워드를 붙인 것만으로 Promise 객체를 리턴하고 있다.
일반 함수처럼 다룰 수 없다는 걸 깨달아 버렸다.. 이제 어떻게 할까?
Promise 객체처럼 then
, catch
로 후속처리를 할 수 있지만
새로운 await
키워드를 이용해서 코드를 async
함수를 다뤄보자
await
은 Promise
가 reject인지 fulfilled인지 상관 없이 일단 끝날 때까지 기다리는 특징을 가지고 있다.
await
은 resolve
함수가 호출될 때까지 기다린다.
reject 가 호출됐을 땐 pending
상태에 머물러 있음을 알 수 있다.
function setTimeoutPromise(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), ms);
});
}
async function startAsync(age) {
// 리턴한 값은 resolve, reject에 해당하는 값은 error 로 해결
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
}
async function startAsyncJobs() {
await setTimeoutPromise(1000);
const promise1 = startAsync(25);
try {
const value1 = await promise1; // *
console.log(value1);
} catch (e) {
console.error(e);
}
const promise2 = startAsync(15);
try {
const value2 = await promise2; // *
console.log(value2);
} catch (e) {
console.error(e);
}
}
startAsyncJobs();
await + Promise 객체
resolve
함수를 호출하기를 기다린다.resolve
값으로 간주한다.value1 // ${age} success
value2 // ${age} is not over 20
throw error
로 처리되는 값이 reject
값으로 간주되고비동기 함수로 시작한 작업은 그로부터 파생한 모든 작업도 비동기 작업으로 간주할 수 있다.
이게 무슨 소리지??
말 그대로 동기 환경
에서는 비동기로 처리한 작업을 기다리지 않고 내 할 일을 하고 있기 때문에 비동기 작업 안에서 동기 작업이 발생하는지 신경쓰지 않는다.
하지만 비동기 환경
에서 비동기 작업의 결과를 기다리는 건 의미가 있는데
예를 들어 '이번 달에 생일인 친구들의 목록을 받아온 뒤 생일 파티를 준비' 하려면 일단 이번 달 생일인 친구들을 찾아내서 결과를 받아야 한다.
무작정 아무 친구나 생일 준비를 해줄 수 없으니 말이다.
이럴 때 await
을 사용하는 것이다.
Promise 작업 끝남
-> 후속 조치
-> resolve : then
-> reject : catch
|
|
await 함수
|
↓
Promise 작업 진행
-> resolve를 기다림(await)
- 원하는 코드 실행
-> reject로 error 발생
- catch 로 예외 처리
작업이 끝나고 후속처리를 하는 방법대신
하나의 async 흐름에서 기다렸다가 다음 코드를 실행하는, 우리가 그동안 해온 느낌으로 비동기 작업을 다룰 수 있게 된다!
출처:
https://elvanov.com/2597 - [Javascript] 비동기, Promise, async, await 확실하게 이해하기