제목이 어그로성이긴 하지만... 이번 포스팅의 내용은 async / await을 사용하는 경우 놓칠 만한 오류가 있으니, 주의하자라는 내용을 담고자 하는 내용이니, 참고하자.
Array.protoype.*
// server api
const checkValidation = async (v) => v % 2
const filteredList = [ 1, 2, 3, 4 ].filter( async (v) => checkValidation(v) )
console.log('filteredList', filteredList) // [1, 2, 3, 4]
위의 결과를 생각을 한 번 해보도록 하자, checkValidation이라는 서버 api가 있을 때, 이 처럼 개발되어있다는 것은 filteredList에 [1, 3]과 같이 홀수만 남아 있기를 원하는 것일 것이다.
하지만, filter입장에서는 async 키워드가 달려있는 순간, Promise를 리턴 받았으니, trucy값으로 판단 하여, [1, 2, 3, 4] 값을 리턴 하게 된다.
Promise.resolve([1, 2, 3, 4])
.then( list => list.reduce( async (acc, v) => {
acc = await acc
if( await checkValidation(v) ) acc.push( v )
return acc
}, Promise.resolve( [] ) ) )
.then(console.log) // [1, 3]
정상적으로 홀수만 반환 받기를 원한다면, 위 처럼 Promise객체 기반으로 작동 할 수 있도록 작성하는 것이 맞다.
filter함수는 promise를 리턴 받는 순간, trucy로 인식하기 때문에 사용을 하는 순간 재기능을 할 수가 없다.
언젠가는 AsyncIterator기반의 컬렉션 함수들이 만들어지게 되면, 위의 내용도 해결 될 수 있지 않을까한다.
setTimeout
setTimeout은 webApi중 대표적으로 평가를 지연시킬 수 있는 함수이다. 간단한 예제를 한 번 보자.
async function delay(v) {
setTimeout(() => {
console.log(`${v}초 후 실행`)
return v
}, v * 1000)
}
delay(2)
.then(console.log) // undefined
// 2초 후 실행
위의 결과도 개발자 입장에서는 2초 후 .then의 결과로 2를 받고 싶었던 것일 것이다. 하지만, undefined를 받을 뿐더러 즉각 받게 될 것이다.
이런 경우에는 Promise.resolve를 사용해야 한다.
function delay(v) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`${v}초 후 실행`)
resolve(v)
}, v * 1000)
})
}
delay(2)
// 2초 후 실행
.then(console.log) // 2
async의 경우 return되는 값을 resolve될 뿐 resolve가 되는 시점에 대해서는 제어가 불가능 하다. 뭐 promise기반의 비동기 함수라면, await키워드를 사용하여, 동기방식으로 제어가 가능 하지만, setTimeout은 프라미스 기반이 아니다.
await이 필요 없는 경우
이건 하지말아야 할 행위 중 하나이다. 왜 일까? 다음 함수를 보자.
async function step1() {
return 1
}
console.log(step1()) // Promise {<fulfilled>: 1}
async키워드를 사용 하는 순간 return의 값은 무조건 promise가 되버리게 된다. 이게 문제가 되는 이유는 그 이후에 저 함수를 사용 하는 경우 async / await을 전부 사용해야 하기 때문이다.
async function step2() {
return await step1()
}
async function step3() {
return await step2()
}
async function step4() {
return await step3()
}
async function step5() {
return await step4()
}
코드 또한 문제가 되지만, 저렇게 되면, 마이크로태스크로 분류 된다. 마이크로태스트의 실행은 이벤트루프에 의해 제어가 되고, callstack에서만 처리되는 것보다, 조금이나마 딜레이 된다.
댓글
댓글 쓰기