Develop/JavaScript

중첩된 Promise<Promise<T>>를 조심해!

안다희 2023. 1. 25. 00:00
728x90

async await 을 함수에서 리턴을 할 때 주의할 점이 있다.

 

Bad 사례처럼, 이미 async가 붙은 함수에서는 리턴값 가장 바깥에 Promise<>가 붙기 때문에,

리턴값은 Promise<>가 붙으면 안된다.

  updateUserGoalVisible = async (
    goalId: number,
    visible: boolean,
  ): Promise<Goal> => {
    /*
     👎 Bad
     이미 async가 붙었기 때문에 리턴값은 순수한 Goal이어야 하는데,
     this.prisma.goal.update({}) 를 리턴함으로써 리턴값은 Promise<Goal>이 되어버린다.
     그래서 이 함수의 최종 리턴값은 Promise<Promise<Goal>> 이 되는 것이다.
     */
    return this.prisma.goal.update({
      where: {
        id: goalId,
      },
      data: {
        isVisible: visible,
      },
    });

    /*
     👍 Good
     await this.prisma.goal.update({})이 순수한 Goal이므로,
     이 함수의 최종 리턴값은 Promise<Goal> 이 된다.
     */
    return await this.prisma.goal.update({
      where: {
        id: goalId,
      },
      data: {
        isVisible: visible,
      },
    });
  };

 

관련 자료

https://github.com/microsoft/TypeScript/issues/27711

Promise<Promise<T>>는 존재할 수 있냐 없냐에 대한 열띤 토론이 이뤄지고 있다..

위 Bad 예시가 문제가 없었던 이유는, 여러번 wrapping된 Promise여도 결국에는 다 까지기 때문이 아닌가 싶다. 

그러나 가끔 시간차?의 문제로 다 까지지 않아 기대되는 리턴값을 리턴하지 못하는 것인가?

 

포스팅 배경

운영중인 서비스에서 가끔 이러한 서버 로그가 찍혔다.

eachDailyMission.commonDailyMission에서 eachDailyMission은 항상 null이 아닌 값인데, 못찾는다는 것이다.

-> 해당 함수를 보니, 리턴값이 Promise<Promise<T>>이었다. 그래서 가끔 리턴값이 T가 아닌 한겹만 벗겨진 Promise<T>여서 그랬던거 아닌가 싶다.

TypeError: Cannot destructure property 'commonDailyMission' of 'eachDailyMission' as it is null.

 

잘못된 부분이 있다면 댓글로 알려주시면 감사하겠습니다!

 

참고하면 좋을 글

https://jojoldu.tistory.com/699

출처: https://mingos-habitat.tistory.com/34 [밍고의서식지:티스토리]