여러개의 API 호출 시에는 Promise.all

sham·2024년 2월 25일

리펙토링 일지

목록 보기
2/2

개요

여러 개의 배열에 특정 값을 전부 수정하는 요청을 보내야 할 때, 주로 다음과 같은 형태의 코드를 작성하곤 했다.


      const result = arrayData.map(async data => {
        await postAPI(data);
      }
      if (result.status)
      {
      	const newData = await getAPI();
        setData(newData);
      }

그런데 이런 구조로 요청을 보낸 후 수정된 데이터를 반영하려고 GET 요청을 보내면 대부분 POST 하기 전 시점의 데이터를, 다시 말해 최신 상태의 데이터를 받아오지 못하는 것이었다. 어째서인지 이유를 도통 알 수 없었는데, 그 이유를 이제서야 깨달았다.

본론

map 함수는 배열을 반환한다

map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다.

위와 같은 구조를 짤 때 나의 추측으로는 await을 사용했기 때문에 각 요소를 돌 때마다 POST 요청이 끝날 때까지 대기할 것이라고 생각했지만, 그건 반만 맞는 이야기였다.

map을 돌면서 마주치는 await 키워드는 API 호출 할때의 비동기 연산이 끝날 때까지 기다리겠지만, map 함수 자체는 그 어떤 비동기 연산도, 요구도 없었기에 배열의 모든 요소의 명령은 내리지만 코드의 흐름은 다음 코드로 넘어가게 되는 것이다.

async 함수는 Promise를 리턴한다

 	await Promise.all(arrayData.map(async data => {
    	await postAPI(data);
      });
	const newData = await getAPI();
	setData(newData);

async 함수는 비동기 요청을 전제로 하기에 무조건 Promise를 리턴하고, 각 요소들에 async 함수를 작성한 arrayData.map이 최종적으로 리턴하는 것은 Promise들로 된 배열들이다.

이 모든 Promsise 요청들이 끝날 때까지 대기하고 싶다면, map을 통해 리턴되는 Promise 배열에 await Promise.all()를 붙여서 모든 Promise가 끝날때까지 기다려야 하는 것이다.

레퍼런스 (Promise, async, await)

https://springfall.cc/article/2022-11/easy-promise-async-await

profile
씨앗 개발자

0개의 댓글