문종현 2022. 10. 29. 17:41

몹시 껄끄러워보이는 코드

프로젝트를 하면서 반복문 안에 비동기 함수를 쓸 경우가 생겼다.

  findOneOrder = async (orderId) => {
    const foundOrder = await this.orderRepository.findOneOrder(orderId);
    console.log(foundOrder.get());

    const { records } = foundOrder;
    console.log("records:", records);
    const parsedRecords = JSON.parse(records);
    console.log("parsedRecords:", parsedRecords);

    const menuList = [];


	for (let i = 0; i < parsedRecords.length; i++) {
      let menuId = parsedRecords[i].menuId;
      let count = parsedRecords[i].count;

      if (!menuId || !count) break;

      let menu = await this.orderRepository.findOneMenu(menuId);
      let Menu = {
        menuId: menu.menuId,
        name: menu.name,
        price: menu.price,
        count,
        image: menu.image,
      };
      menuList.push(Menu);
    }
   
   const data = {
      orderId: foundOrder.orderId,
      orderDate: foundOrder.createdAt,
      storeId: foundOrder.Store.storeId,
      storeName: foundOrder.Store.name,
      storePhone: foundOrder.Store.storePhone,
      menuList,
    };
    console.log(data);

    return data;
  };

 

물론 작동이야 하지만, 규모가 아주 작은 프로젝트이기 때문이다.

데이터 양이 커지기 시작하면 문제가 될 것을 예상하기란 쉬운 일이다.

 


편해진 코드

  findOneOrder = async (orderId) => {
    const foundOrder = await this.orderRepository.findOneOrder(orderId);
    console.log(foundOrder.get());

    const { records } = foundOrder;
    console.log("records:", records);
    const parsedRecords = JSON.parse(records);
    console.log("parsedRecords:", parsedRecords);

    const menuList = [];
    
    const promises = parsedRecords.map(async (record) => {
      let menuId = record.menuId;
      let count = record.count;

      if (menuId && count) {
        let menu = await this.orderRepository.findOneMenu(menuId)
        let Menu = {
          menuId: menu.menuId,
          name: menu.name,
          price: menu.price,
          count,
          image: menu.image,
        };
        return menuList.push(Menu)
      }
     });
    
     await Promise.all(promises) 
    
    console.log("menuList:", menuList);

    const data = {
      orderId: foundOrder.orderId,
      orderDate: foundOrder.createdAt,
      storeId: foundOrder.Store.storeId,
      storeName: foundOrder.Store.name,
      storePhone: foundOrder.Store.storePhone,
      menuList,
    };
    console.log(data);

    return data;
  };

Promise.All 을 써야겠다는 생각을 품고는 있었지만, 배열 반복문의 경우 어떻게 적용할지 조금의 고민이 있었다.

물론 이런 문제는 대개 샤워를 하거나 하늘을 쳐다보거나 고양이를 구경하다보면 방법이 떠오르기 마련이다.

 

map 은 비동기마저 콜백으로 잘 받아주고 프로미스 객체들로 이루어진 배열을 반환해준다. 

이렇게 기특할 수가 없다.

 


아직 남은 의문

대체 저 배열 안의 프로미스 객체들은 어떻게 생겼을까. 

    const menuList = [];
    
    const promises = parsedRecords.map(async (record) => {
      let menuId = record.menuId;
      let count = record.count;

      if (menuId && count) {
        let menu = await this.orderRepository.findOneMenu(menuId)
        let Menu = {
          menuId: menu.menuId,
          name: menu.name,
          price: menu.price,
          count,
          image: menu.image,
        };
        return menuList.push(Menu)
      }
     });
    
     console.log(promises)

     const result = await Promise.all(promises) 
     console.log(result)

 

console.log(promises) 의 결과다.

네번째가 undefined인 것은, 들어간 배열 중 앞의 세개만 if문을 통과하기 때문이다.

네번 것은 menuId나 count가 아닌, 다른 정보가 들어간 객체이다. 

[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { undefined }
]

 

console.log(result)의 결과다.

[ 1, 2, 3, undefined ]

 

저 1, 2,3은 무엇일까?