데이터가 많아져서 .then()을 사용하게 되는 순간 비동기의 위험성이 존재한다.
이때는 Promise를 통해 전체 비동기화를 진행해야한다.
최근에 외주 프로젝트를 진행하면서 일어난 버그와 문제에 대해서 기록으로 남겨본다.
//문제의 코드 영역
const payload: UserPayload = {
...(await this.userRepository
.findOne({
select: this.userSelectInfoList,
where: {
userId: authTokenDto.loginId,
userUuid: authTokenDto.uuid,
},
})
.then(async (res) => {
if (res) {
const queryRunner = await this.datasource.createQueryRunner()
await queryRunner.startTransaction()
try {
const lastestLoginInfo = await queryRunner.manager.findOne(
User,
{
where: {
userId: authTokenDto.loginId,
userUuid: authTokenDto.uuid,
},
},
)
.
.
.
//개선한 코드 영역
//then절을 사용하지 않고 await를 사용하여 비동기화
const payload: UserPayload = await this.userRepository.findOne({
select: this.userSelectInfoList,
where: {
userId: authTokenDto.loginId,
userUuid: authTokenDto.uuid,
},
})
if (!payload) {
await this.datasource
.createQueryBuilder()
.insert()
.into(User)
.values([
{
userId: authTokenDto.loginId,
userUuid: authTokenDto.uuid,
userSchoolCode: authTokenDto.scCode,
userSchoolName: authTokenDto.scName,
isTermOn: isNewMember ? true : false,
},
])
.execute()
isFirstVisit = true
} else {
if (payload.userUuid !== authTokenDto.uuid) {
throw new BadRequestException('diff uuid')
}
const queryRunner = this.datasource.createQueryRunner()
await queryRunner.startTransaction()
🚀 then()을 사용해야 하는 경우
❓ then()을 언제 사용해야 할까?
1. Promise 체이닝을 사용해야 하는 경우
• 여러 개의 비동기 요청을 순차적으로 실행해야 할 때
• await을 사용할 수 없는 문맥 (예: .map() 내부)
2. 콜백 스타일 코드와 호환해야 할 경우
• 예전 코드에서 Promise 기반으로 작성되어 있을 때
3. 즉시 실행할 필요가 없고, 이후 체인에서 데이터를 사용해야 할 경우
- then()을 사용할 때는 반드시 return을 명확히 해야 함.
- catch()에서 예외 처리를 해야 예기치 않은 undefined 반환을 방지할 수 있음.
- await을 사용할 수 있으면 가급적 await을 사용하는 것이 더 안전함.