[JS] forEach 사용시 async 함수 호출

최근에 업무중 forEach로 순회하며 api 호출 후 결과를 받아서 다음 작업을 수행해야하는 경우가 있었다.

일단 api가 list형태로 파라미터를 던져서 한번에 조회 결과를 반환해주면 성능 면에서 더 좋을텐데, 굳이 단건 호출만 가능하도록 api를 제공하니 어쩔 수 없이 forEach로 순회하며 여러번 api를 호출할 수 밖에 없었다.

어쨋든 의도는 forEach로 순회하며, async 함수로 api를 호출 후 결과를 받아서 값을 셋팅해야 하는데, 돌려보니 비동기 호출 후 결과가 오기를 기다리지 않고 그냥 다음 순회를 돌아버리는 문제가 있었다.

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 web docs를 찾아보니 forEach는 promises를 기다리지 않는다고 한다.

그래서 더 찾아보니 for of문을 이용하는 방법이 있는데, 이 방법은 순차적으로 처리하다 보니 병렬처리가 아니라서 순회건수가 많으면 시간이 오래걸리는 문제가 있고,

병렬처리를 위해서는 Promise.all()을 이용하는 방법이 있다.

비동기로 호출해야 하는 api 호출 부분을 Promise배열로 만들고, Promise.all()을 통해 실행하면 비동기 함수들을 병렬로 동시에 처리할 수 있다.

let apis = [];

const promises = this.sourceList.map(async (x) => {
const api = await calledApi({key: x.value});
apis.push(api);
});

await Promise.all(promises);

map()을 통해서 promise배열에 담아서, Promise.all()을 통해 실행할 수 있다.

결론은 순회하면서 비동기 처리가 필요하면 forEach대신에 map(async obj) 형태로 사용하면 된다.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.