NestJS控制器中如何检测服务空返回结果并抛出异常
问题原因
服务层的getPreferences是异步函数,返回值为Promise类型。你在控制器中调用该方法时没有加await等待异步执行完成,此时拿到的永远是pending状态的Promise实例,不管数据库实际返回空还是有值,都无法通过直接判断变量拿到真实结果。另外你原来的判断条件写反了:有结果时不应该抛异常,只有返回空值时才需要触发404。
正确实现方式
第一步:修改服务层代码
既然要把异常抛出逻辑迁移到控制器,服务层就不再保留非空校验,直接返回数据库查询结果即可,同时补全返回值类型:
async getPreferences(eUserId: string): Promise<UserPreferences | null> { return this.userPreferencesModel.findOne({ eUserId, }); }
返回值类型加| null是因为Mongoose的findOne方法查不到匹配数据时会返回null,类型定义需要和实际返回逻辑一致。
第二步:修改控制器代码
调用服务层方法时添加await关键字,等待异步查询完成拿到真实返回值后,再做非空判断、抛出异常:
@Get() async getPreferences( @Headers('x-e-user-id') eUserId: string, ): Promise<UserPreferences> { // 等待异步执行完成,拿到真实查询结果 const userPreferences = await this.userPreferencesService.getPreferences(eUserId); console.log('userPreferences: ', userPreferences); // 结果为空时抛出404异常 if (!userPreferences) { throw new NotFoundException("We couldn't find your user preferences"); } return userPreferences; }
可选写法
如果你不想用async/await,也可以用Promise链式调用实现相同效果,不过可读性稍差:
@Get() getPreferences( @Headers('x-e-user-id') eUserId: string, ): Promise<UserPreferences> { return this.userPreferencesService.getPreferences(eUserId) .then(userPreferences => { if (!userPreferences) { throw new NotFoundException("We couldn't find your user preferences"); } return userPreferences; }) }
补充提示:NestJS内置了全局异常过滤器,不管在控制器层还是服务层抛出的HttpException都会被统一捕获、返回标准格式的错误响应。如果服务层的这个方法会被多个控制器或者其他服务复用,把非空判断和异常抛出留在服务层反而能减少重复代码,维护性更好。
内容的提问来源于stack exchange,提问作者DavSev
相关产品推荐
相关产品推荐

