在 NestJS 中,当你使用了@Res()(或@Response())装饰器时,NestJS 会进入**“库原生模式”(Library-specific mode)**。
原因分析
一旦你在路由处理函数中注入了@Res(),NestJS 就失去了对响应流的自动控制权。此时,NestJS 不再理会函数的return值,它会认为你将手动处理响应(例如通过调用res.send()或res.json())。
在你提供的代码中:
- 你使用了
@Res() res: Response。 - 你写了
return ret;。 - 由于 NestJS 在等待你手动调用
res的方法来结束请求,而你一直没调用,请求就会一直挂起(Pending),直到浏览器或服务器超时。
解决方案
你有三种方式可以解决这个问题:
方案一:手动调用res.send()或res.json()(推荐用于需要精细控制响应的情况)
既然你已经引入了res对象,就直接使用它来发送数据:
@Get('confirm-email')asyncconfirmEmail(@Query('code')code:string,@Res()res:Response){letret={code:RETCODE.EMAIL_CONFIRMATION_FAILED,access_token:null,message:'Error 9004',};constuserCode=awaitthis.loginService.getCode(code,1);if(!userCode){console.log('User code not found');returnres.status(200).json(ret);// 使用 res.json() 发送响应}// 注意:其他逻辑路径也必须通过 res 发送响应}方案二:使用passthrough: true(最推荐:既想用 res 又想用 return)
如果你只想用res来设置一些东西(比如 Cookie、Header),但仍然希望由 NestJS 来处理return的返回值,可以设置passthrough参数:
@Get('confirm-email')asyncconfirmEmail(@Query('code')code:string,@Res({passthrough:true})res:Response){letret={code:RETCODE.EMAIL_CONFIRMATION_FAILED,access_token:null,message:'Error 9004',};constuserCode=awaitthis.loginService.getCode(code,1);if(!userCode){returnret;// 此时 return 生效了,NestJS 会自动包装成 JSON 发送}}方案三:移除@Res()(最简洁)
如果你在函数体里根本没用到res对象(比如只是为了定义类型却没调用它的方法),直接删掉它。这是 NestJS 的推荐做法,它会自动处理return的对象。
@Get('confirm-email')asyncconfirmEmail(@Query('code')code:string){// 移除 @Resletret={code:RETCODE.EMAIL_CONFIRMATION_FAILED,access_token:null,message:'Error 9004',};constuserCode=awaitthis.loginService.getCode(code,1);if(!userCode){returnret;// 正常工作}}总结
在 NestJS 中,一旦用了@Res(),你就得对响应负责。如果不调用res.send()或设置passthrough: true,客户端将永远等不到响应。