AMQP使用topic exchange测试nack时报错TypeError问题咨询
排查RabbitMQ Topic Exchange中nack使用导致的错误
嘿,我来帮你搞定这两个RabbitMQ的错误,其实都是代码里的几个小细节没处理对:
第一个错误:AMPQ: TypeError: Cannot read property 'deliveryTag' of undefined
这个问题完全是因为你调用ch.nack()的姿势不对。RabbitMQ的nack方法要求第一个参数必须是收到的消息对象(也就是那个msg参数),但你现在传的是字符串'error occurred'——这显然不是一个消息对象,内部代码尝试读取它的deliveryTag属性时自然就会抛出“读取undefined属性”的错误。
第二个错误:UnhandledPromiseRejectionWarning
这个警告有两个触发原因:
- 你把消费回调写成了
async函数,在async函数里抛出同步错误(比如你写的throw 'error occurred')会被自动包装成一个被拒绝的Promise。虽然你写了try/catch,但还有另一个关键问题: - 你设置了
{noAck: true},这意味着RabbitMQ会在消息推送给消费者后自动确认消息,这种情况下你再调用nack是完全无效的,甚至会引发额外的异步错误,因为消息已经被自动确认了,手动拒绝的操作已经没有意义,进而导致Promise状态异常。
修正后的完整代码
ch.bindQueue(q.queue, ex, 'key'); ch.consume(q.queue, async (msg) => { console.log(" Sub: [x] %s:'%s'", msg.fields.routingKey, msg.content.toString()); const eventInfo = JSON.parse(msg.content.toString()); try { throw 'error occurred'; } catch(err) { console.error('处理消息时出错:', err); // 正确调用nack:第一个参数是消息对象,后面两个参数按需调整 // 第二个参数allUpTo:是否拒绝所有未确认的消息,这里设为false // 第三个参数requeue:是否将当前消息重新放回队列,这里设为true(可根据需求改false) ch.nack(msg, false, true); } }, {noAck: false}); // 必须设为false,才能手动执行nack/ack操作
关键修正点说明
- 关闭自动确认:把
{noAck: true}改成{noAck: false},这样才能手动控制消息的确认或拒绝流程。 - 正确调用nack:第一个参数传入真正的消息对象
msg,后面的两个参数可以根据你的业务需求调整是否批量拒绝、是否重新入队。 - 错误捕获完善:现在
try/catch能正确捕获async函数内的错误,不会再出现未处理的Promise拒绝警告。
内容的提问来源于stack exchange,提问作者user269867
相关产品推荐
相关产品推荐

