mqtt.js 客户端封装

mqtt.js 客户端封装

没封装前使用

js 复制代码
const client = mqtt.connect('ws://10.10.20.9:9001')
onMounted(() => {
  const topicList = []
  const channelCount = 12
  for(let i = 0; i < channelCount; i++) {
    topicList.push(`/test/sendImage${i + 1}`)
  }

  client.on('connect', () => {
    console.log('connected')
    topicList.forEach((topic) => {
      client.subscribe(topic)
    })
    client.on('message', (topic, message) => {
      // 主要差别在这里,需要判断 topic 是当前订阅的,才进行处理,
      // 每次需要遍历所有的 topic 
      topicList.forEach((t, index) => {
        if(topic === t) {
          handleImage(message, index)
        }
      })
    })
  })
  client.on('error', (error) => {
    console.error('mqtt connect error', error)
  })
})
onUnmounted(() => {
  client.end()
})

封装后使用

js 复制代码
const client = new Mqtt()
client.connect('ws://10.10.20.9:9001')

onMounted(() => {
  const topicList = []
  const channelCount = 12
  for(let i = 0; i < channelCount; i++) {
    topicList.push(`/test/sendImage${i + 1}`)
  }
  topicList.forEach((topic, index) => {
    // 订阅topic时,注册 callback,
    // 当前topic接收到的数据在 callback 中处理
    client.subscribe(topic, (message) => {
      handleImage(message, index)
    })
  })
})
onUnmounted(() => {
  client.disconnect()
})

封装 Mqtt class

原理是 subscribe 时,注册当前topic处理的 callback,在callback中处理接收到的数据

ts 复制代码
import mqtt, { IClientOptions, MqttClient } from 'mqtt';

export class Mqtt {
  private client: MqttClient | null = null;

  /**
   * 连接到 MQTT 服务器
   * @param brokerUrl
   * string: MQTT 服务器地址,
   * IClientOptions: 客户端配置
   * @param opts
   * @returns
   */
  connect(brokerUrl: string): MqttClient
  connect(opts: IClientOptions): MqttClient
  connect(brokerUrl: string, opts?: IClientOptions): MqttClient
  connect(
    brokerUrl: string | IClientOptions,
    opts?: IClientOptions,
  ): MqttClient {
    if(this.client) {
      console.warn('MQTT client is already connected.');
      return
    }
    // 如果第一个参数是 IClientOptions 类型,则将其赋值给 opts
    if(typeof brokerUrl === 'object') {
      opts = brokerUrl;
      brokerUrl = ''; // 如果 brokerUrl 是空字符串,mqtt.connect 会使用 opts 中的 brokerUrl
    }

    // 确保 opts 不为空
    opts = opts || {};

    // 调用 mqtt.connect
    this.client = mqtt.connect(brokerUrl, opts);
    this.client.on('connect', () => {
      console.log('Connected to MQTT broker');
    })
    this.client.on('error', (error) => {
      console.error('MQTT error:', error);
    });

    this.client.on('close', () => {
      console.log('Disconnected from MQTT broker');
    });
    return this.client;
  }

  /**
  * 订阅主题
  * @param topic 主题
  * @param callback 消息回调函数
  */
  subscribe(topic: string, callback: (message: any) => void): void {
    if(!this.client) {
      console.error('MQTT client is not connected.');
      return;
    }
    this.client.subscribe(topic, (err) => {
      if(err) {
        console.error('Subscription error:', err);
      } else {
        console.log(`Subscribed to topic: ${topic}`);
      }
    });
    this.client.on('message', (receivedTopic, message) => {
      if(receivedTopic === topic) {
        callback(message);
      }
    })
  }

  /**
  * 发布消息到主题
  * @param topic 主题
  * @param message 消息内容
  */
  ppublish(topic: string, message: any) {
    if(!this.client) {
      console.error('MQTT client is not connected.');
      return;
    }
    this.client.publish(topic, message, (err) => {
      if(err) {
        console.error('Publish error:', err);
      } else {
        console.log(`Message published to topic: ${topic}`);
      }
    })
  }

  /**
   * 断开连接
   */
  disconnect() {
    if(this.client) {
      this.client.end();
      this.client = null;
    }
  }
}

结语:

以上是对 mqtt.js 的简单业务封装。当然还有其他的封装方式,只需要满足当前的业务需求即可。

相关推荐
起床学FPGA17 小时前
AI回答问题之后,会自动跳到最下面的问题
开发语言·javascript·ecmascript
Fluxart.ai17 小时前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
why技术18 小时前
AI 写的文章,可能都带着手敲一遍都去不掉的“隐形水印”。
前端·人工智能·后端
愚公搬代码18 小时前
【愚公系列】《Android应用案例开发大全》016-LBS类应用掌上杭州(辅助工具类的开发)
android·前端
CodeSheep18 小时前
又一个华为天才少年,离职了!
前端·后端·程序员
kyriewen18 小时前
面试官说"打开你的AI工具"——我才发现,他考的根本不是写代码
前端·人工智能·面试
IT_陈寒19 小时前
Vue的双向绑定把我坑惨了,原来这个场景不能用
前端·人工智能·后端
hunterandroid20 小时前
[Android 从零到一] Compose LazyColumn 性能优化:key、稳定性与重组治理
android·前端
lichenyang45320 小时前
从一次团队邀请开始:用 React、NestJS 与 Socket.IO 做可靠的实时通知
前端
vtian20 小时前
一篇文章吃透 Monorepo:pnpm + Turborepo + Changesets 全流程实战(含 8 个踩坑)
前端