T.I.L

23-08-03 forEach와 비동기

김민커 2023. 8. 3. 22:14

문제설명

req.body에서 받아온 객체의 데이터를 배열화 한 다음에 forEach로 데이터베이스와 body의 데이터가 유효한지 검증하는 로직을 설정했다. 하지만 에러가 발생했고 console.log로 forEach의 인자를 찍어보았다.

그리고 Promise {pending}이라는 결과를 얻었다. 

 

시도

forEach는 배열의 모든 요소마다 설정한 로직을 수행하는 기능이다. 여기서 중요한 점은 forEach는 로직을 수행하기만 할 뿐 각 로직에 대한 결과의 출력을 기다리지 않는다. 그래서 가장 먼저 시작한 로직이 가장 늦게 될 수도 있는 것이고 나중에 시작된 로직이 먼저 결과를 출력할 수도 있는 것이다. 즉 forEach는 비동기적 함수라는 의미이다.

 

Promise {pending}은 로직의 진행 순서를 말한다. pending은 준비를 뜻 한다. 아직 로직이 시작하지 않았다는 것이다.

준비상태가 끝나면 fulfill과 reject 단계로 나뉜다. fulfill은 진행을 의미하고 reject 는 거부를 의미한다.

 

fulfill은 결과를 출력하거나 동기적인 함수가 있다면 그 함수를 실행한다, 아니면 다시 pending 단계를 거처서 .then()이나 .catch()의 단계로 진행할 수 있다

.

reject는 바로  .then()이나 .catch()의 단계를 거치거나 에러핸들링의 단계로 진행한다.

 

forEach자체에 async await를 사용해서 로직이 수행이 되야 다음 로직이 수행되도록 할 예정이다.

 

해결

    itemOrderList.forEach(async(itemOrder) => {
      const existingItem = await Item.findOne({ where: { id: itemOrder[0] } });
      console.log(existingItem)
      if (existingItem==null) {
        return {
          status: 400,
          errorMessage: "판매하지 않는 상품이 존재합니다.",
        };
      }

      if (existingItem.amount < itemOrder[1]) {
        return {
          status: 400,
          errorMessage: `${existingItem.name}의 재고가 주문량 보다 적게 있습니다.`,
        };
      }
    });

화살표 함수의 형식으로 forEach 내부의 함수 자체에 async await를 부여해서 로직이 단계적으로 작동이 되도록 했다.

 

알게된 점

1.forEach는 비동기적 메서드이기 때문에 다른 함수가 포함이 된다면 pending을 야기한다.

2.forEach의 pending을 방지하기 위해서는  async await를 forEach의 내부함수에 적용해야한다.

3.pending=>fulfill/reject 의 관계를 이해할 수 있었다.