이게 답은 아닙니다.
지극히 개인적인 코드입니다.
제가 잘 모르기에 조언은 얼마든지 환영입니다.
반복적인 값을 계속해서 서버에 요청을 보내고 그 값들을 모아서 한번에 리턴하는 함수를 작성해보았습니다.
단, 이 함수들의 순서는 중요함으로 promise.all 사용은 배제했습니다.
const timeoutFunc = (idx) =>
new Promise(resolve=>setTimeout(()=>resolve(`result ${idx}`),1000))
async function test(){
const arr = Array(10).fill(0)
return new Promise(async(res,rej)=>{
const result = []
for(let x in arr){
const _result = await timeoutFunc(x)
result.push(_result)
}
res(result)
})
}
await test()
// ['result 0', 'result 1', 'result 2', 'result 3', 'result 4', 'result 5', 'result 6', 'result 7', 'result 8', 'result 9']
이와 같은 로직에서 제가 겪은 문제는 forEach
문이었습니다.
위 코드를 아래와 같이 바꾸면
const timeoutFunc = (idx) =>
new Promise(resolve=>setTimeout(()=>resolve(`result ${idx}`),1000))
async function test(){
const arr = Array(10).fill(0)
return new Promise(async(res,rej)=>{
const result = []
arr.forEach(async(a,i)=>{
const _result = await timeoutFunc(i)
result.push(_result)
})
res(result)
})
}
await test()
// []
와 같은 결과를 얻을 수 있습니다.
바뀐건 for - of
을 forEach
로 변경한 것 뿐입니다.
왜 그런것일까요?
forEach() expects a synchronous function — it does not wait for promises. Make sure you are aware of the implications while using promises (or async functions) as forEach callbacks.
MDN에서는 이것을 친절히 설명해주고 있었습니다.
const ratings = [5, 4, 5];
let sum = 0;
const sumFunction = async (a, b) => a + b;
ratings.forEach(async (rating) => {
sum = await sumFunction(sum, rating);
});
console.log(sum);
// Naively expected output: 14
// Actual output: 0
결과값이 14가 나올 것 같았지만 0이 나왔습니다. 이렇듯 forEach의 콜백함수는 오직 동기적으로만 사용해야하고 반복문에서 비동기인 문법을 사용하기 위해서는 for-of
,for
,promise.all
등을 사용해야합니다.
저는 이러한 것을 알지 못하고 계속해서 forEach로 접근하여 문제를 풀려다가 못풀었지만, 이 글을 읽는 누군가는 저와 같은 문제를 겪지 않으셨으면 좋겠습니다.