JavaScript

forEach와 async await (for of 사용하기)

citron031 2022. 10. 29. 21:40

🥝 forEach는 promises를 기다리지 않기에 async await 구문 역시 동작하지 않는다.

const setTimeoutPlus = (num1, num2) => {
  return new Promise((resolve, reject) => {
    try {
      setTimeout(() => {
        resolve(num1 + num2);
      }, 3000);
    } catch (e) {
      reject("ERROR", e);
    }
  })
}

const asyncForEachFuc = (data) => {
  let tmp = [];
  console.log("start", tmp);
  data.forEach(async function(element,index,array){
    tmp.push(await setTimeoutPlus(element + index));
  });
  console.log("end", tmp);
  return tmp;
}

console.log("print", asyncForEachFuc([1, 2, 3, 4, 5]));
  • 위의 코드는 start, end, print 모두 빈 배열이 출력된다.
const setTimeoutPlus = (num1, num2) => {
  return new Promise((resolve, reject) => {
    try {
      setTimeout(() => {
        resolve(num1 + num2);
      }, 3000);
    } catch (e) {
      reject("ERROR", e);
    }
  })
}

const asyncForEachFuc = async (data) => {
  let tmp = [];
  console.log("start", tmp);
  let index = 0;
  for(let i of data) {
    tmp.push(await setTimeoutPlus(i, index));
    index += 1;
  }
  console.log("end", tmp);
  return tmp;
}

asyncForEachFuc([1, 2, 3, 4, 5]).then(el => console.log("print", el));
  • 위의 코드는 start는 빈 배열이 출력되나, 시간이 지난 뒤 end와 print에 [1,3,5,7,9] 배열이 출력된다.
const setTimeoutPlus = (num1, num2) => {
  return new Promise((resolve, reject) => {
    try {
      setTimeout(() => {
        resolve(num1 + num2);
      }, 300);
    } catch (e) {
      reject("ERROR", e);
    }
  })
}

const asyncForEachFuc = async (data) => {
  let tmp = [];
  console.log("start", tmp);
  let index = 0;
  for await (i of data) {
    tmp.push(await setTimeoutPlus(i, index)); 
    index++;
  }
  console.log("end", tmp);
  return tmp;
}

asyncForEachFuc([1, 2, 3, 4, 5]).then(el => console.log("print", el));
  • 위와 같은 for await 구문도 있는데, for await는 비동기 iterators를 처리하는 데 적합하다. 중간에 promises가 reject되어도 처리가 계속 되기 때문이다.
  • 또한, 모든 요청을 하나씩 보내고 기다리는 작업을 반복하게 된다.
  • for of와 for await of는 비슷하게 작동하나, 명시적으로 순차적인 처리가 일어남을 나타낼 수 있게 for await of를 사용한다.
  • 대신에 Promise.all을 사용하면, 요청을 한 번에 보내고 reject시 에러를 받을 수 있다.
const setTimeoutPlus = (num1, num2) => {
  return new Promise((resolve, reject) => {
    try {
      setTimeout(() => {
        resolve(num1 + num2);
      }, 300);
    } catch (e) {
      reject("ERROR", e);
    }
  })
}

const asyncForEachFuc = async (data) => {
  let tmp = [];
  console.log("start", tmp);
  tmp = await Promise.all(data.map((el, index) => setTimeoutPlus(el, index)));
  console.log("end", tmp);
  return tmp;
}

asyncForEachFuc([1, 2, 3, 4, 5]).then(el => console.log("print", el));
  • Promise.all은 요청을 한 번에 보내기에 for문보다 빠르게 처리된다.

 

참고 자료
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for-await...of

https://stackoverflow.com/questions/59694309/for-await-of-vs-promise-all

https://stackoverflow.com/questions/71100058/why-eslint-no-await-in-loop-not-working-with-for-await-of

 

Why ESLint no-await-in-loop not working with for await of?

for await of — supposed to be used with asynchronous iterators, it awaits each promise within iterator and handles response of each awaited promise in its body. From MDN docs this syntax can be use...

stackoverflow.com

 

for await of VS Promise.all

Is there any difference between this: const promises = await Promise.all(items.map(e => somethingAsync(e))); for (const res of promises) { // do some calculations } And this ? for await (co...

stackoverflow.com

 

for await...of - JavaScript | MDN

for await...of 구문은 보통 비동기에 대응하는 열거자를 나열할 때 쓰이지만, String, Array, Array 같은 객체 (e.g., arguments or NodeList), TypedArray, Map, Set 같은 동기적으로 열거 가능한 객체 또한 가능하며,

developer.mozilla.org

 

Array.prototype.forEach() - JavaScript | MDN

The forEach() method executes a provided function once for each array element.

developer.mozilla.org