You need to enable JavaScript to run this app. 使用mqttjs连续发布多个Buffer时仅重复输出最后一个值问题求解
优惠活动
大模型
产品
解决方案
定价
更多

使用mqttjs连续发布多个Buffer时仅重复输出最后一个值问题求解

问题原因

这一问题是Node.js Buffer的引用类型特性与MQTT.js publish方法的异步执行逻辑共同导致的,和MQTT服务端、MQTT.js库本身的bug无关,属于JavaScript语法层面的常见误区。

具体原因拆解

  • Node.js中的Buffer属于引用类型,你全程仅初始化了一个Buffer实例,所有对buf[0]的修改都是在操作同一块内存地址存储的值,没有生成新的副本。
  • client.publish是异步方法,循环调用时仅会将发送任务推入Node.js事件队列,不会立刻执行网络发送操作。而for循环是同步执行的,等循环跑完时buf[0]已经被递增到0xff,事件队列中排队的多个publish任务才会依次执行,此时读取同一个Buffer拿到的都是最终的0xff值。

你观察到的特殊现象也完全符合该逻辑:先调用publish将发送任务入队后,同步执行的for循环会立刻将Buffer值修改为0xff,等publish实际执行读取Buffer内容时,拿到的自然已经是修改后的值。
而连续发布字符串没有问题,是因为字符串属于JavaScript值类型,传入publish时会自动传值而非传引用,后续修改不会影响已经入队的任务内容。

修复方案

方案1:循环内每次创建新的Buffer实例(推荐)

每次发布都生成独立的Buffer,互不干扰:

client.on('connect', function () {
  client.subscribe('LED', function (err) {
    if (!err) {
      for (let val = 0xfa; val < 0xff; val++) {
        const buf = Buffer.from([val]);
        client.publish('LED', buf);
      }
    }
  })
})

方案2:复用Buffer改为串行异步发送

如果需要复用同一个Buffer,需要等待前一条消息确认发送完成后,再修改Buffer值发送下一条:

// 先将publish封装为Promise适配async/await语法
const publishAsync = (client, topic, payload) => {
  return new Promise((resolve, reject) => {
    client.publish(topic, payload, (err) => err ? reject(err) : resolve())
  })
}

client.on('connect', async function () {
  client.subscribe('LED', async function (err) {
    if (!err) {
      const buf = Buffer.from([0xfa]);
      for (; buf[0] < 0xff; buf[0]++) {
        await publishAsync(client, 'LED', buf);
      }
    }
  })
})

内容的提问来源于stack exchange,提问作者Jdm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 06:39:02