리액트를 사용하면서 js를 사용할일이 잦아졌다.
axios를 사용할때나, 화면을 지연없이 그릴일이 많아져서 그런것같다.
사용할때마다 헷갈리는 Promise 체이닝과 async await개념을 명확히 하여 클-린한 코드를 작성할 수 있도록 해보자.
1. 비동기 함수 작성
어느날 소희는 아래와 같은 비동기 함수를 작성했다. 입력받은 숫자에서 10을 더하는 함수이다.
const sum10 = (number) => {
let count = 0;
let timerId = setInterval(() => {
console.log(++number);
if(++count === 10){clearInterval(timerId)}
}, 1000)
}
1-1. 콜백지옥 문제 인식하기.
하지만 언제나 그렇듯, 기획이 급하게 변경되어서 함수를 수정해야 하는 상황이 되었다.
sum10()을 실행하고 반환받은 값에서 sum10을 한번 더 호출 해야만 했다. 어떻게 할것인가?
소희는 급한 나머지 아래와 같은 코드를 작성한다.
const sum10 = (number) => {
let count = 0;
let timerId = setInterval(() => {
console.log(++number);
if(++count === 10){
clearInterval(timerId)
/* 3월 19일 JIRA 이슈 수정을 위해 추가 */
let count2 = 0;
let timerId2 = setInterval(() => {
console.log(++number);
if(++count2 === 10){
clearInterval(timerId2)
}
}, 1000)
}
}, 1000)
}
// 호출 sum10(0)
// 1...20 출력
위 코드의 가장 큰 문제는 다른사람이 코드를 이해하고 수정하기가 어렵다는것이다.
또는 다시 기획이 변경되어 여러번 수정해야 한다는 문제가 왔다면... timer3, timer4... 중복된 코드가 무한히 추가될것이다..
2. Promise로 변경하기
Promise체이닝을 사용하면 콜백이 무한히 이어지는 함수를 깔끔하게 정리 할 수 있다.
sum10()함수를 Promise를 반환하는 함수로 변경해줬다.
const sum10 = (number) => {
return new Promise((resolve,reject) => {
let count = 0;
let timerId = setInterval(() => {
console.log(++number);
if(++count === 10){
clearTimeout(timerId)
resolve(number);
}
}, 1000)
})
}
그리고 아래와 같이 호출해준다.
Promise를 return하는 함수를 호출 후, then에서 다시 Promise를 반환하는 함수를 호출하는게 Promise 체이닝의 핵심이다.
sum10(0)
.then((number) => {
return sum10(number);
}).then((number) => {
console.log('end!');
})
// 1..20 출력
결과는 두 함수가 같다. 하지만 2번 코드가 유지보수가 더 간편하다는것을 알 수 있다.
다시 10을 더해야 한다면, 마지막 줄에 return sum10(number)을 입력해 주면 끝난다.
3. async/await 사용하기
sum10함수 호출을 async await와 같이 사용한 코드는 아래와 같다.
더 깔끔해졌다.
여기서 헷갈린점은, Promise의 then처럼 어떤 결과를 전달받고 싶다면,
Promise를 반환하는 함수를 호출하면서, 그 Promise내부의 함수는 resolve(/*반환할 값*/) 을 호출해야 한다는것이다.
await sum10(0)은 그래서 반환값으로 10을 받을 수 있었다.
testAsyncAwait = async () => {
let number = await sum10(0);
number = await sum10(number);
}
testAsyncAwait()
// 1...20 출력
3-1 async함수 호출 꼼수
await는 최상위에 있을수 없다. 무슨말이냐 하면 항상 async설정된 함수의 내부에 있어야 한다는 말이다.
즉시호출 async함수를 사용하면 함수를 생성하지 않고 바로 실행할 수 있다.
(하지만 사용하지 말자..)
(async (number) => {
number = await sum10(number);
number = await sum10(number);
})(10)
'Today I learned' 카테고리의 다른 글
2022 03 20 react 함수형 컴포넌트 (0) | 2022.03.20 |
---|---|
2022 03 20 - 단축평가 (0) | 2022.03.20 |
2021 11 20 혼돈의 Optional 훈련 (0) | 2021.11.20 |
20201 11 19 - 혼돈의 Optional (0) | 2021.11.19 |
2021 11 18 stream은 손에 안익네.. (0) | 2021.11.18 |
댓글