반복적인 비동기 처리

김병민·2022년 11월 27일
0

자바스크립트 공부

목록 보기
16/16
post-thumbnail

이게 답은 아닙니다.
지극히 개인적인 코드입니다.
제가 잘 모르기에 조언은 얼마든지 환영입니다.

반복적인 값을 계속해서 서버에 요청을 보내고 그 값들을 모아서 한번에 리턴하는 함수를 작성해보았습니다.
단, 이 함수들의 순서는 중요함으로 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 - offorEach로 변경한 것 뿐입니다.

왜 그런것일까요?

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로 접근하여 문제를 풀려다가 못풀었지만, 이 글을 읽는 누군가는 저와 같은 문제를 겪지 않으셨으면 좋겠습니다.

profile
I'm beginner

0개의 댓글