Node.js/TypeScript

[TypeScript] 비동기 - promise 안에 promise? Promise.all()로 처리

왈왈디 2023. 5. 19. 16:59
728x90

아래와 같이 TypeScript로 함수를 만들었는데, Promise<CarModel>[] 같이 배열 안에 Promise 객체들이 담긴 이상한 return 값이 나왔다. 

registerNewModel(newModels: NewModelDto[]): Promise<CarModel>[] {
    return newModels.map(async (newModel) => {
      const isExisting = await this.carModelsRepository.findOneBy({
        name: newModel.name,
      });
      if (isExisting) {
        return isExisting;
      }
      const brand = await this.brandRepository.findOneBy({
        name: newModel.brand,
      });
      const engineSize = await this.engineSizeRepository.findOneBy({
        size: newModel.engineSize,
      });
      const carType = await this.carTypeRepository.findOneBy({
        type: newModel.carType,
      });

      const createdModel = this.carModelsRepository.create({
        name: newModel.name,
        capacity: newModel.capacity,
      });

      createdModel.brand = brand;
      createdModel.engineSize = engineSize;
      createdModel.carType = carType;

      this.carModelsRepository.save(createdModel);

      return createdModel;
    });
  }

함수 전체에 async를 걸어주면 2중으로 promise가 걸려서

Promise<Promise<CarModel>[]> 같은 요상한 모양의 return값만 나오고 전혀 소용이 없었다.

 

통신 결과는 빈 객체만 담긴 배열이 나왔다.

 

어떻게 해결해야하나 싶었는데,

Chat GPT에게 물어보니 다음과 같이 답변해줬다.

registerNewModel 함수는 map 메서드를 사용하여 newModels 배열을 비동기적으로 처리하고 있습니다.
각각의 요소에 대해 async 함수를 사용하여 Promise를 반환하고 있기 때문에, registerNewModel 함수 자체도 Promise 배열을 반환하고 있습니다.
비동기 작업을 수행하는 함수를 사용하는 경우, 결과가 완전히 처리되기 전에 함수가 반환되는 문제가 발생할 수 있습니다.
따라서, registerNewModel 함수가 모든 비동기 작업이 완료된 후에 결과를 반환하도록 수정해야 합니다.
이를 위해 Promise.all() 메서드를 사용할 수 있습니다.
Promise.all() 메서드를 사용하여 모든 Promise가 완료될 때까지 대기하고 그 결과를 반환합니다.
이렇게 하면 모든 비동기 작업이 완료된 후에 결과 배열이 제대로 반환될 것입니다.

시키는 대로 return 값에 아래와 같이 Promise.all() 메서드를 걸어주니 일반적인 Promise 객체로 잘 반환되었다.

registerNewModel(newModels: NewModelDto[]): Promise<CarModel[]> {
    const createdModels = newModels.map(async (newModel) => {
      const isExisting = await this.carModelsRepository.findOneBy({
        name: newModel.name,
      });
      if (isExisting) {
        return isExisting;
      }
      const brand = await this.brandRepository.findOneBy({
        name: newModel.brand,
      });
      const engineSize = await this.engineSizeRepository.findOneBy({
        size: newModel.engineSize,
      });
      const carType = await this.carTypeRepository.findOneBy({
        type: newModel.carType,
      });

      const createdModel = this.carModelsRepository.create({
        name: newModel.name,
        capacity: newModel.capacity,
      });

      createdModel.brand = brand;
      createdModel.engineSize = engineSize;
      createdModel.carType = carType;

      this.carModelsRepository.save(createdModel);

      return createdModel;
    });

    return Promise.all(createdModels); //Promise.all()로 promise 풀어주기
  }
728x90