비동기 프로그래밍을 동기 프로그래밍의 방식으로 작성하는데에 특화되어진 문법입니다.
Promise의 then사용 방식보다 가독성이 더 좋으나, Promise는 반환하는 비동기상태값에 대한 제어가 가능하기 때문에, 좀 더 포괄적인 개념을 가진다고 볼 수 있습니다.
async function getData() {
return 123;
}
getData().then((data) => console.log(data));
async await에서 반환하는 값은 promise입니다. 그렇기 때문에 그 상태와 데이터를 그대로 반환할 수 있습니다.
async function getData() {
return Promise.resolve(123);
//return Promise.reject(123); 만약이렇게 reject를 넘겨준다면, catch부분이 실행 될 겁니다.
}
getData()
.then((data) => console.log("fulfilled", data))
.catch((data) => console.log("rejected", data));
위처럼 넘겨주는 promise의 상태값에 따른 처리가 가능한 코드를 작성할 수 있습니다.
async 를 사용하는 함수 내부에서는 await를 사용하는 것이 가능합니다.
await 키워드 오른쪽에 Promise객체를 입력하게 되면, 해당 promise객체가 settled가 될 때까지 기다리게 됩니다.
fullfilled(제대로 진행) 됐을 때에는 지정한 변수에 해당 값이 들어가게 됩니다.
async function printData() {
const data1 = await requestData(10);
const data2 = await requestData(20);
console.log(data1, data2);
}
printData();
// result :: data1함수가 실행 및 끝이나고, 그다음 data2가 실행됩니다.
async awiat는 그 promise의 상태와 데이터를 그대로 반환처리합니다.
async function getData() {
console.log("getData 1");
await Promise.reject();
console.log("getData 2");
await Promise.resolve();
console.log("getData 3");
}
getData()
.then(() => console.log("fulfilled"))
.catch((error) => console.log("rejected"));
위에서 Promise.reject(); 를 통해 호출이 끝나버리고, reject상태의 promise를 반환하기 때문에, catch의 구문이 동작하게 됩니다.
결과
$ node class.js
getData 1
rejected
awiat 키워는 async await함수 내부에서만 활용가능합니다.
아래처럼 일반함수에서는 await키워드를 사용할 수 없습니다.
function getData() {
const data = await requestData(10);
console.log(data);
}
비동기함수와 비동기함수간의 연계가 높아질수록 async await과 promise의 가독성의 차이가 드러납니다.
function getDataPromise() {
return asyncFunc1()
.then((data1) => Promise.all([data1, asyncFunc2(data1)]))
.then(([data1, data2]) => {
return asyncFunc3(data1, data2);
});
}
async function getDataAsync() {
const data1 = await asyncFunc1();
const data2 = await asyncFunc2();
return asyncFunc3(data1, data2);
}
async await에서 여러함수를 병렬로 처리하는 방법은 이와 같습니다.
두개의 promise객체를 생성하여, await키워드를 사용하게되면 병렬로써 실행하게 됩니다.
...
async function getData() {
const p1 = asyncFunc1();
const p2 = asyncFunc2();
const data1 = await p1;
const data2 = await p2;
console.log({ data1, data2 });
}
getData();
반대로, Promise객체를 활용하면 이코드가 더 간단해지게 됩니다.
두개의 Promise객체를 매개변수로써 입력하고 있기 때문에 앞전코드처럼 병렬처리가 진행하게 됩니다.
...
async function getData() {
const [data1, data2] = await Promise.all([asyncFunc1(), asyncFunc2()]);
//...
}
이처럼 동기함수와 비동기함수가 공존하는 경우에 대해서는 catch문을 통한 예외처리가 가능하다.
async function getData() {
try {
await doAsync();
return doSync();
} catch (error) {
console.log(error);
return Promise.reject(error);
}
}
then메소드를 사용하는 객체는 promise처럼 취급되어진다. (이를 Thenable이라고 한다.)
await을 통해서 아래처럼 사용하는 것을 확인 할 수 있다.
class ThenableExample {
then(resolve, reject) {
setTimeout(() => resolve(123), 1000);
}
}
async function asyncFunc() {
const result = await new ThenableExample();
console.log(result);
}