함수 앞에 async가 오게 되면 그 함수는 Promise이 된다.
const passOrfailed1 = () => {
return new Promise((respond, reject) => {
respond('pass');
});
}
const passOrfailed2 = async () => {
return 'pass';
}
passOrfailed는 1,2로 구분되어 있다. 1번은 기존의 Promise를 리턴하는 방식이고 2번은 async를 이용한 방
법이다. 코드가 상당히 간단해 진것을 알수 있다.
const delay = (sec) => {
return new Promise ((res) => {
setTimeout(res, sec*1000);
})
}
const getFruit = async () => {
await delay(1);
return 'apple';
}
getFruit().then((ele) => console.log(ele));
위 코드는 delay(sec)함수는 Promise로 getFruit()는 async로 사용했습니다. 두개의 함수가 선언되고 getFruit()를 실행하면 1초 대기 하다가 respond로 apple 문자열이 출력됩니다. 그리고 .then에서 그 문자열('apple')을 ele 전달인자에 받아서 console.log로 출력을 해줍니다.
delay를 여러 군데에서 사용할수도 있다.
const delay = (sec) => {
return new Promise ((res) => {
setTimeout(res, sec*1000);
})
}
const getFruit1 = async () => {
await delay(1);
return 'apple';
}
const getFruit2 = async () => {
await delay(2);
return 'tomato';
}
const getFruit3 = async () => {
await delay(1);
return 'orange';
}
getFruit1().then((ele) => console.log(`1초후에 ${ele}`));
getFruit2().then((ele) => console.log(`2초후에 ${ele}`));
getFruit3().then((ele) => console.log(`1초후에 ${ele}`));
위 코드를 보면 getFruit 1,2,3이 각각 1,2,1초의 delay가 주어진 것을 알수 있다. console.log도 1,2,3순서로 되어 있지만 실제 출력은 1,3,2이다
이는 각각의 console.log에서 getFruit의 대기 시간을 기다린 다음에 실행이 되는 것이다. 1,3번의 1초씩 같아서 거의 동시에 출력이 되고 2번은 2초의 대기시간이 있기 때문에 다른 함수들에 비해 1초 더 늦게 출력이 되는 것이다.
const delay = (sec) => {
return new Promise ((res) => {
setTimeout(res, sec*1000);
})
}
const getFruit1 = async () => {
await delay(1);
return 'apple';
}
const getFruit2 = async () => {
await delay(2);
return 'tomato';
}
const getFruit3 = async () => {
await delay(1);
'orange';
}
const getAll = () => {
getFruit1().then((ele1) => {
getFruit2().then((ele2) => {
getFruit3().then((ele3) => {
return `${ele1} ${ele2} ${ele3}`;
})
})
})
}
getAll().then(console.log);
이제 then을 이용하여 모든 과일들을 출력하는데 위의 코드처럼 이용할수 있습니다. (4초 걸림) 하지만 async(또는 Promise)가 3개 이상만 되도 코드가 상당히 알아보기가 어렵습니다.
const getAll = async () => {
const f1 = await getFruit1();
const f2 = await getFruit2();
const f3 = await getFruit3();
return `${f1} ${f2} ${f3}`;
}
getAll()함수를 위와 같이 변경을 하면 코드가 상당히 깔끔해 진것을 알수 있다.
순서도를 보면 알겠지만 f1,f2,f3를 순서대로 선언하고 마지막에 리턴을 한 것이다. f를 선언하는 각 단계가 끝나기 전까지는 다음단계로 이동하기 않는다. 따라서 각각 1,2,1초씩 걸리기 때문에 실제 출력은 4초후에 한다.
하지만 이렇게 하면 각 단계별로 실행되는 시간을 기다려야 하기 때문에 비효율 적이다. 병렬로 처리할수 있는 코드는 바로바로 실행되는것이 효율적이기 때문에 다음 코드를 참고 하시기 바람
const getAll = async () => {
const f1_promis = getFruit1();
const f2_promis = getFruit2();
const f3_promis = getFruit3();
const f1 = await f1_promis;
const f2 = await f2_promis;
const f3 = await f3_promis;
return `${f1} ${f2} ${f3}`;
}
이번에는 getAll()함수 내부를 수정하였다. 이전의 Promis에서 설명했듯이 Promise는 선언동시에 실행이 된다. 따라서 f1_promis는 선언 동시에 1초후에 완료가 된다. f2_promis도 마찬가지로 선언 동시에 2초후에 완료가 된다. 이렇듯 서로 병렬로 실행되면 f1_promis가 선언되는 1초가 동시에 f2_promis도 선언을 하는 것이다.
결국 출력되는데 총 2초만 소요가 된다.
하지만 위의 코드는 많이 지저분 하여 아래와 같이 변경이 가능하다.
const getAll = () => {
return Promise.all([getFruit1(),getFruit2(),getFruit3()])
.then(ele => ele.join(' '));
}
Promise의 all method를 사용하여 return을 하는 것이다. 배열
[getFruit1(),getFruit2(),getFruit3()]
은 Promise 상태의 ['apple', 'tomato', 'orange']로 변경이 되며 .then에서 문자열로 join을 한다.
당연히 다음 코드에서 이것을 console.log로 출력할때 기존과 같은 'apple tomato orange' 가 출력되게 된다.
const delay = (sec) => {
return new Promise ((res) => {
setTimeout(res, sec*1000);
})
}
const getFruit1 = async () => {
await delay(1);
// throw 'error';
return 'apple';
}
const getFruit2 = async () => {
await delay(2);
return 'tomato';
}
const getFruit3 = async () => {
await delay(1);
return 'orange';
}
const getFirst = () => {
return Promise.race([getFruit1(),getFruit2(),getFruit3()]);
}
getFirst().then(console.log);
만약 가장 먼저 출력되는 것을 알고 싶으면 Promise의 race method를 사용하면 됩니다. getFirst에서 race method는 getFruit의 1,2,3중에서 가장 빨리 return하는 것을 출력합니다. 이때 2번은 1,3번에 비해 1초 느리기 때문에 출력이 단됩니다. 그럼 1,3중에서 1이 먼저 출력됨을 알수 있습니다.
이유는 배열상 1번이 3번에 비해 인덱스가 작기 때문입니다. 그래서 설사 같은 delay가 1초여도 1번이 실질적으로 먼저 완료가 되는 것입니다.
댓글
댓글 쓰기