await과 async는 새로운 것이 아니라 promise 위에서 동작하는 api로
promise를 동기적으로 보일 수 있도록 하는 Syntantic Sugar라고 할 수 있다.
프로미스는 체이닝이 가능하기 때문에 자칫하면 콜백처럼 체이닝으로 코드가 지저분해보일 수 있는데
await와 async의 사용으로 이를 간결하게 만들 수 있다.
Promise와 Async
//Promise
function fetchUser1() {
return new Promise((resolve, reject) => {
//do network request in 10 sec....
resolve("ellie");
});
}
const user1 = fetchUser1();
user1.then(console.log);
프로미스를 사용한 코드
// async
async function fetchUser2() {
//do network request in 10 sec....
return "ellie";
}
const user2 = fetchUser2();
user2.then(console.log);
async를 사용한 경우
결국 async는 Promise를 생성하는 Producer의 모양만 바꿀 뿐 Promise 생성이라는 동일한 역할을 하게 된다.
async를 사용한 Producer은 동기적인 함수와 생김새가 다르지 않다.
동기적인 함수는 아래와 같은 함수를 말한다.
function fetchUser() {
//do network request in 10 secs.....
return "ellie";
}
const user = fetchUser();
console.log(user);
하지만 사용할 때에는(Consumer일 때에는) .then .catch .finally 등 Promise와 동일한 코드로 사용한다.
Async와 Await
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return "🍎";
}
async function getBanana() {
await delay(1000);
return "🍌";
}
위에 작성된 await은 delay 함수를 기다려주는 역할을 한다.
이때 await의 대상(delay)는 반드시 Promise를 반환해주어야 한다.
대부분 프로미스를 반환하는 API 호출 함수가 대상이 된다.
await을 사용하지 않으면 기존 Promise처럼 then을 사용하거나 callback 함수를 사용해야한다.
그러나 await을 사용함으로써 delay 함수를 동기적인 척! 쓸 수 있다.
위의 함수와 Promise를 사용하여 과일들을 출력하면 이렇게 쓸 수 있다.
function pickFruits() {
return getApple().then((apple) => {
return getBanana().then((banana) => `${apple} + ${banana}`);
});
}
pickFruits().then(console.log);
2초가 있다가 🍎 + 🍌가 출력되게 된다.
그러나 체이닝 과정을 거치면서 코드가 많이 복잡해졌다.
async와 await을 활용하여 이를 고쳐볼 수 있다. 역시 아래의 코드도 2초 있다가 실행된다.
async function pickFruits2() {
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits2().then(console.log);
Async와 Await의 에러처리
에러 처리 또한 throw error, try~catch로 해주면 되기 때문에 기존 코드와 유사하다.
에러 처리 예시)
async function getApple() {
await delay(1000);
throw 'error'
return "🍎";
}
async function pickFruits2() {
try{
const apple = await getApple();
const banana = await getBanana();
}catch(){
}
return `${apple} + ${banana}`;
}
pickFruits2().then(console.log);
Await 병렬처리
위의 코드는 잘 작동하지만 getApple과 getBanana는 서로 독립된 실행임에도 불구하고
순차적으로 실행되어 시간이 낭비되는 단점이 있다.
따라서 Promise는 생성될 때 바로 실행된다는 점을 이용하여 병렬처리를 할 수 있다.
async function pickFruits3() {
const applePromise = getApple();
const bananaPromise = getBanana();
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits3().then(console.log);
그러나 이것보다 더 간단한 방법이 있다. 병렬 처리를 지원하는 Promise api, Promise.all()을 활용하는 것이다.
아래와 같이 병렬처리된 Promise의 리턴값을 배열로 받아올 수 있다.
function pickAllFruits()
{
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join( ' + '))
}
pickAllFruits().then(console.log)
Promise.all 외에도 시간이 적게 걸리는 Promise를 받아오고 싶다면
Promise.race()를 사용할 수 있다.
function pickOnlyOne(){
return Promise.race([getApple(), getBanana()])
}
pickOnlyOne().then(console.log)
'javascript' 카테고리의 다른 글
클린코드 - 변수다루기 (0) | 2022.06.03 |
---|---|
[함수형 자바스크립트] 객체의 불변성을 관리하는 방법들 (0) | 2020.11.30 |
[함수형 언어, 자바스크립트] 비동기 처리 (2) Promise의 이해 (0) | 2020.11.17 |
[함수형 언어, 자바스크립트] 비동기 처리 (1) Callback 함수의 이해 (0) | 2020.11.17 |
[함수형 언어, 자바스크립트] 배열에 함수 체이닝 (1) (0) | 2020.10.22 |