다음과 같은, 사용자 정보를 가져오는 함수가 있다.
function fetchUser(){
//fetching user info which takes 10 secs
return 'user data';
}
const user = fetchUser();
console.log(user);
이 fetchUser() 안의 작업이 10초가 걸리는 작업이라고 가정하자. 이때, fetchUser()가 실행되는 동안 다른 작업을 하지 못하게 된다. 만일 이 뒤에 ui를 렌더링하는 코드가 있다고 하면, 사용자는 10초간 텅 빈 화면을 보고 있을 것이다. 즉 '하나가 끝나고→다른 하나를 부름' 순으로 작동한다면 이러한 문제들이 나타날 가능성이 크다.
앞 코드를 비동기 방식으로 바꿔 보자.
async function fetchUser(){
//fetching user info which takes 10 secs
return 'user data';
}
const user = fetchUser();
console.log(user);
함수 앞에 async
을 붙여 주면, 함수 안 코드 블록들이 자동으로 Promise 로 변환된다.
즉 async
함수는 Promise를 리턴하며, Promise 의 resolve 값은 함수에서 리턴한 값이 된다(여기서는 'user data')
async 함수 안에 await을 사용해 delay를 만들어 줄 수 있다.
async function getPencil() {
await delay(1000);
return 'pencil'
}
//1초의 딜레이가 끝날 때까지 기다렸다가 'pencil' 리턴
async function getEraser() {
await delay(2000);
return 'eraser'
}
//2초의 딜레이가 끝날 때까지 기다렸다가 'eraser' 리턴
이번에는 promise가 중첩되어 읽기 불편한 코드를 async/await으로 깔끔하게 바꿔 보자.
function makePencilCase(){
return getPencil().then(pencil => {
return getEraser().then(eraser => `${pencil},${eraser}`)
})
}
makePencilCase().then(console.log)
//async,await 사용
async function makePencilCase() {
const pencil = await getPencil();
const eraser = await getEraser();
}
makePencilCase().then(console.log)
async와 await을 사용하여 비동기 코드를, 우리가 동기적으로 코드를 작성하듯 할 수 있다.
에러 처리의 경우 try, catch를 사용하자.
//async,await 사용
async function makePencilCase() {
try{
const pencil = await getPencil();
const eraser = await getEraser();
}catch{
}
}
makePencilCase().then(console.log)
이 예제를 보면, pencil이 끝나고 나서 eraser가 호출된다. 그런데 여기서 pencil과 eraser는 서로 연관성이 없는데, 굳이 pencil이 끝날 때까지 기다려야 할까? 병렬로 처리할 수는 없을까?
async function makePencilCase() {
//await 병렬 처리
//promise를 만드는 순간,promise안에 있는 코드 블록이 실행됨.
const pencilPromise = getPencil();
const eraserPromise = getEraset();
const pencil = await pencilPromise;
const eraser = await eraserPromise;
//pencil과 eraser를 동시에 집어서 필통에 넣음
return `${pencil},${eraser}`;
}
이렇게 되면 pencil과 eraser를 동시에 집어서 필통에 넣을 수 있어서 더 효율적이다.
사실 병렬 처리를 하려는 경우 이러한 방식으로 코드를 짜기보다는 promise API를 이용해 더 깔끔하게 짜도 된다. 😉 요건 다음 포스팅에서!
게임 유저 데이터를 받아서, 점수가 100점 이상일 때만 새 아이템을 지급하는 함수를 만들어 보자.
async function giveRewardItem() {
const user = await getJSON();
if(user.score >= 100){
const reward = await generateRewardItem(user)
return reward;
}else{
console.log(user)
return user;
}
}
const api = {
fetchUsers: async (keyword) => {
try{
const response = await fetch(`/api/users/search?q=${keyword}`)
if(response.ok){
return response.json();
}
}
catch(e){
console.error(e.status);
}
}
}