高声望用户评价问题时出现Cannot read properties of undefined错误排查
问题描述
开发了一个异步功能,用于实现高声望用户对普通用户的问题进行点赞或点踩:当问题获得-1票时,普通用户会扣除声望。但运行时出现错误:
ERROR [RpcExceptionsHandler] Cannot read properties of undefined (reading 'voto')
移除voto字段后,id、titulo等其他DTO属性也会报类似错误,疑似未获取到Postman的请求数据。相关代码如下:
问题服务(RabbitMQ)代码
async usuarioPrestigiadoAtualiza(idUsuario: string, idUsuarioPropio: string, idPergunta: string, dados: atualizaEspecificoDTO) { const usuario = await this.usuarioMetaRepository.findOne({where: {id: idUsuario}}) if(usuario === null){ throw new NotFoundException('Usuario Prestigiado nao existe') } const usuario2 = await this.usuarioMetaRepository.findOne({where: {id: idUsuarioPropio}}) if(usuario2 === null){ throw new NotFoundException('Usuario Propio nao existe') } const perguntaAchada = await this.perguntaRepository.findOne({where: {id: idPergunta}}) if(perguntaAchada === null){ throw new NotFoundException('Pergunta nao existe') } if(usuario.prestigio < 100){ throw new UnauthorizedException(`Usuario: ${usuario.nome} nao possui prestigio suficiente!`) } if (dados.voto === -1) { usuario2.prestigio -= 5; usuario2.voteForce -= 2; } else if (dados.voto >= 1) { for (let i = 0; i < 100; i++) { if (usuario2.pergunta.voto + 1) { usuario2.prestigio += 4; usuario2.voteForce += 1; } } } if (usuario.voteForce > 30) { dados.voto *= 2; } if (usuario.voteForce > 60) { dados.voto *= 3; } if (usuario.voteForce >= 100) { dados.voto *= 4; } if(usuario2.prestigio >= 100){ usuario2.prestigio === 100 } perguntaAchada.id = dados.id perguntaAchada.titulo = dados.titulo perguntaAchada.voto = dados.voto perguntaAchada.pergunta = dados.pergunta const perguntaMudadaPorPrestigiado = await this.perguntaRepository.save(perguntaAchada) console.log(perguntaMudadaPorPrestigiado) return perguntaMudadaPorPrestigiado }
RabbitMQ控制器代码
@MessagePattern({ cmd: 'put-perguntaPrestigio'}) async enviarPerguntaAvaliada(@Ctx() contexto: RmqContext, @Payload() payload: { idUsuario: string; idUsuarioPropio: string; idPergunta: string; dados: atualizaEspecificoDTO }) { const channel = contexto.getChannelRef() const message = contexto.getMessage() channel.ack(message) return this.perguntaService.usuarioPrestigiadoAtualiza(payload.idUsuario, payload.idUsuarioPropio, payload.idPergunta, payload.dados )
API网关控制器代码
@Put('usuarioM/:id1/:id2/:id3') async perguntaAtualizaPorPrestigiado(@Param('id1') idUsuario: string, @Param('id2') idUsuarioPropio: string, @Param('id3') idPergunta: string, @Body() data: atualizaEspecificoDTO) { return this.authServico.send( { cmd: 'put-perguntaPrestigio' }, {idUsuario, idUsuarioPropio, idPergunta, data} ) }
解决方案
1. 修复请求数据传递的字段名不匹配问题
这是导致dados为undefined的核心原因:
- API网关控制器发送RabbitMQ消息时,传递的字段是
data,但RabbitMQ控制器的payload期望接收的是dados字段,字段名不匹配导致payload.dados始终为undefined。 - 调整API网关代码,将
data改为dados字段:
@Put('usuarioM/:id1/:id2/:id3') async perguntaAtualizaPorPrestigiado(@Param('id1') idUsuario: string, @Param('id2') idUsuarioPropio: string, @Param('id3') idPergunta: string, @Body() data: atualizaEspecificoDTO) { return this.authServico.send( { cmd: 'put-perguntaPrestigio' }, {idUsuario, idUsuarioPropio, idPergunta, dados: data} ) }
2. 修复代码中的逻辑错误
- 赋值操作错误:
usuario2.prestigio === 100是比较运算符,无法实现声望上限限制,需改为赋值操作usuario2.prestigio = 100。 - 无效循环逻辑:
for (let i = 0; i < 100; i++)内的if (usuario2.pergunta.voto + 1)永远为true(除非voto=-1),会执行100次声望和voteForce累加,不符合业务预期,需根据实际需求调整判断条件,比如改为单次累加而非循环。 - 不必要的ID更新:
perguntaAchada.id = dados.id无意义,已通过idPergunta查到对应问题实体,无需修改ID,仅更新其他业务字段即可。
3. 验证DTO定义正确性
确保atualizaEspecificoDTO类正确定义了voto、titulo、pergunta等字段,并使用class-validator和class-transformer装饰器(如@IsNumber()、@IsString()),确保NestJS能正确解析Postman请求体数据。
内容的提问来源于stack exchange,提问作者J. Maciel
相关产品推荐
相关产品推荐

