Promise → then → promise → then → ... 계속 반복해서 사용하면 난잡해짐!
⇒ 이 문제를 해결하고자 등장한게 Async/Await! (Syntactic sugar)
The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains. (비동기적인 코드를 동기적으로 보이도록! 가독성 높아짐)
# Async
async function name([param[, param[, ...param]]]) {
statements
}
이런식으로 앞에 async
키워드를 사용하면 된다.
이렇게 생성한 async함수는 Promise
를 리턴한다 ✨ (resolved의 결과일 수도 있고, reject의 결과일 수도 있음)
# Await
async
함수 안에는 await
표현이 포함될 수 있다.
await
키워드는 promise-based의 비동기 작업이 fulfilled
되거나 rejected
될때까지 기다려줌!
하나의 비동기 작업을 promise와 async로 표현해보면 아래와 같다.
'use strict';
function waitForMe(){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(`Thank you for waiting me 😊`);
}, 3000);
});
}
// 1. promise then
function promiseWait(){
waitForMe().then(console.log);
}
// 2. async await
async function asyncWait(){
const res = await waitForMe();
console.log(res);
}
promiseWait(); // Thank you for waiting me 😊
asyncWait(); // Thank you for waiting me 😊
얼핏 보면 then
이 간단해보일 수 있지만, 계속해서 비동기작업을 해야된다면 Promise chain이 줄줄이 반복되어서 가독성이 떨어진다.
반면 async/await을 이용해 표현한 함수는 동기적인 코드처럼 보이기 때문에 이해하기가 쉬워진다.(syntactic sugar의 힘🍫🍬🧁)
# 조금 더 알아보기
앞에서 말했듯이 Async/Await는 Promise의 Syntactic Sugar다!
그래서 본질적으로는 둘이 똑같은것이다.
'use strict';
async function asyncWay() {
return 1
}
function promiseWay() {
return Promise.resolve(1)
}
console.log(asyncWay()); // Promise {<resolved>: 1}
console.log(promiseWay()); // Promise {<resolved>: 1}
둘 다 똑같이 Promise함수를 만든 것이다!😯👍
# 비동기 처리 순서
동시에 여러개의 비동기를 처리하는 방법은 여러가지가 있다.
하나의 작업이 다 완료되어야 다음 작업을 이어갈 수도 있을 것이고, 둘이 동시에 시작할 수도 있다.
두 가지 작업을 처리해야한다고 치자.
첫 번째 작업은 도리🐟가 밥을 먹는 것이고, 두 번째 작업은 니모🐠가 밥을 먹는 것이다.
니모는 아기라서 밥을 먹는데 5초가 걸리고 도리는 2초가 걸린다.
"use strict";
const nemoEat = function(){
return new Promise((resolve)=>{
setTimeout(()=>resolve(`Nemo finished meals🐠`), 5000);
})
};
const doriEat = function(){
return new Promise((resolve)=>{
setTimeout(()=>resolve(`Dori finished meals🐟`), 2000);
})
};
1. Sequential: 니모가 밥을 다 먹은 후에야 도리가 밥을 먹을 수 있다.
니모가 5초동안 밥을 다 먹은 후에야 도리가 밥을 2초동안 먹는다.
그래서 둘 다 식사를 마무리하는 데까지 총 7초가 걸린다!
console.time()과 console.timeEnd()를 이용해서 시간을 측정했다.
const sequential = async()=>{
console.time('🐠 meal time');
console.time('🐟 meal time');
const nemo = await nemoEat();
console.log(nemo);
console.timeEnd('🐠 meal time');
const dori = await doriEat();
console.log(dori);
console.timeEnd('🐟 meal time');
}
sequential();
// result
// Nemo finished meals🐠
// 🐠 meal time: 5000.904052734375ms
// Dori finished meals🐟
// 🐟 meal time: 7003.98779296875ms
2. Concurrent: 니모랑 도리랑 밥을 같이 먹기 시작한다.
같이 먹기 시작하면 니모는 5초가 걸리고, 도리는 2초가 걸리니까 둘이 함께 식사를 마치는 데는 총 5초가 걸리게 된다. 도리는 니모가 식사를 마칠 때까지 기다렸다가 같이 식사를 마무리한다고 해보자!(니모가 아직 아기라서 챙겨줘야됨👶)
const concurrent = async()=>{
console.time('🐠 meal time');
console.time('🐟 meal time');
// 동시에 밥을 먹기 시작
const nemo = nemoEat();
const dori = doriEat();
console.log(await nemo);
console.timeEnd('🐠 meal time');
console.log(await dori);
console.timeEnd('🐟 meal time');
}
concurrent();
// result
// Nemo finished meals🐠
// 🐠 meal time: 5002.114990234375ms
// Dori finished meals🐟
// 🐟 meal time: 5002.39501953125ms
위 코드는 Promise.all
을 이용한 것과 같은 결과를 나타낸다. (마찬가지로 5초가 걸린다.)
Promise.all 한 번 더 짚고 넘어가기!
The Promise.all() method takes an iterable of promises as an input, and returns a single Promise as an output.
const concurrentWithPromiseAll = ()=>{
console.time('meal time');
Promise.all([nemoEat(), doriEat()])
.then(res=>{
console.log(res[0]);
console.log(res[1]);
console.timeEnd('meal time');
});
}
concurrentWithPromiseAll();
3. ✨ Parallel: 각자 식사를 하고 각자 종료한다. ✨
이제 니모가 다 컸다! 이제 더 이상 도리가 니모의 식사를 기다려줄 필요가 없다. 각자 혼밥하고 식사를 마치면 된다.
도리는 2초만에 식사를 끝낼 수 있고, 니모는 5초동안 먹고 알아서 식사를 마치면 된다.
const parallel = ()=>{
console.time('🐠 meal time');
console.time('🐟 meal time');
Promise.all([
(async ()=>{
console.log(await nemoEat());
console.timeEnd('🐠 meal time');
})(),
(async ()=>{
console.log(await doriEat());
console.timeEnd('🐟 meal time');
})()
])
}
parallel();
//result
// Dori finished meals🐟
// 🐟 meal time: 2001.485107421875ms
// Nemo finished meals🐠
// 🐠 meal time: 5001.932861328125ms
'Javascript' 카테고리의 다른 글
자바스크립트 디자인패턴 - 빌더 패턴(Builder pattern) (0) | 2021.05.18 |
---|---|
함수형 프로그래밍(Functional Programming) (0) | 2020.06.28 |
JavaScript의 Call, Apply, Bind (0) | 2020.06.24 |
객체 내 key 또는 value로 배열 만들기 (0) | 2020.04.06 |
JavaScript 코드 꿀팁들 (0) | 2020.04.05 |