TS MQTT封裝
匯入相關包
npm i mqtt
npm i lodash
- guid 隨機生成就行,具體可以參考百度或者隨便生成一個隨機數*
程式碼封裝
import mqtt from 'mqtt'
import type { MqttClient, OnMessageCallback, IClientOptions, IClientPublishOptions, IPublishPacket } from 'mqtt'
import { getGuid } from '@/common/basic'
import { without, uniq } from 'lodash'
export type TPublishFormat = {
topic: string
payload: string | Buffer
opts?: IClientPublishOptions
}
export type TMessageCallback<T> = (topic: string, payload: T) => void
export interface IMqClientOptions extends IClientOptions {
connectCb?: () => void
errorCb?: (e: Event) => void
reconnectCb?: () => void
}
export default class MQTT {
private _type: string
private _url: string
private _opt: IMqClientOptions // mqtt配置
public client!: MqttClient
public topicArr: Array<string> = []
constructor(url: string, opt?: IMqClientOptions, type: string = 'Web') {
this._type = type
this._url = url
this._opt = {
clean: true,
clientId: this._type + '_' + getGuid(), // 客戶端分類唯一
connectTimeout: 3000, // 超時時間
reconnectPeriod: 1000, //重連超時
...(opt && opt),
}
this._init()
}
private _init() {
this.destroy()
this.client = mqtt.connect(this._url, this._opt)
this.client.on('connect', () => {
this._opt.connectCb && this._opt.connectCb()
console.log(this._url + '連線成功...')
})
this.client.on('error', (error: any) => {
this._opt.errorCb && this._opt.errorCb(error)
console.log(this._url + '異常中斷...')
})
this.client.on('reconnect', () => {
this._opt.reconnectCb && this._opt.reconnectCb()
console.log(this._url + '重新連線...')
})
}
/**
* 函式“unSubscribe”是一個 TypeScript 函式,用於取消訂閱一個或多個主題,並返回一個 Promise,該 Promise 解析為一個布林值,指示取消訂閱是否成功。
* @param {string | string[]} topic - topic 引數可以是字串或字串陣列。它代表客戶端想要取消訂閱的主題。
* @returns 正在返回 Promise。
*/
public unSubscribe(topic: string | string[]) {
return new Promise((resolve: (isOk: boolean) => void) => {
this.client &&
!this.client.disconnected &&
this.client
.unsubscribeAsync(topic)
.then((result) => {
if (typeof topic === 'string') {
topic = [topic]
}
//去重
this.topicArr = without(this.topicArr, ...topic)
console.log(topic, this.topicArr, '取消訂閱成功...')
resolve(true)
})
.catch((err) => {
console.log(topic, '取消訂閱失敗...')
resolve(false)
})
})
}
/**
* 函式“onSubscribe”是一個 TypeScript 函式,它訂閱一個或多個主題並返回一個 Promise,該 Promise 解析為一個布林值,指示訂閱是否成功。
* @param {string | string[]} topic - topic 引數可以是字串或字串陣列。它代表您要訂閱的主題。
* @returns 一個 Promise,解析為布林值,指示訂閱是否成功。
*/
public onSubscribe(topic: string | string[]) {
if (typeof topic === 'string') {
topic = [topic]
}
const topicOk: Array<string> = without(topic, ...this.topicArr)
return new Promise((resolve: (isOk: boolean) => void) => {
this.client &&
!this.client.disconnected &&
topicOk.length > 0 &&
this.client
.subscribeAsync(topic)
.then((result) => {
this.topicArr.push(...topicOk)
this.topicArr = uniq(this.topicArr)
console.log(topicOk, this.topicArr, '訂閱成功...')
resolve(true)
})
.catch((err) => {
console.log(topicOk, '訂閱失敗...')
resolve(false)
})
})
}
/**
* 函式“onPublish”使用客戶端向主題釋出訊息,並返回一個解析為布林值的 Promise,指示釋出是否成功。
* @param {TPublishFormat} format - format引數的型別為TPublishFormat,它是一個包含兩個屬性的物件:topic和message。 topic
* 屬性表示訊息將釋出到的主題,message 屬性表示將釋出的實際訊息。
* @returns 正在返回 Promise。
*/
public onPublish(format: TPublishFormat) {
return new Promise((resolve: (isOk: boolean) => void) => {
this.client &&
!this.client.disconnected &&
this.client
.publishAsync(format.topic, format.payload, format.opts)
.then((result) => {
console.log('釋出訊息成功...')
resolve(true)
})
.catch((err) => {
console.log('釋出訊息失敗...')
resolve(false)
})
})
}
//收到的訊息
public onMessage<T = any>(callback: TMessageCallback<T>) {
this.client &&
!this.client.disconnected &&
this.client.on('message', (topic: string, payload: Buffer) => {
try {
callback && callback(topic, JSON.parse(payload.toString()))
} catch (err) {
console.log('無法執行JSON.parse...')
callback && callback(topic, payload.toString() as T)
}
})
}
//銷燬
public destroy() {
console.log('銷燬...')
this.client && this.client.end()
this.topicArr = []
}
}
使用
//透過開源公共伺服器測試,切換成自家伺服器就行了
const mqtt = new MQTT('mqtt://broker.emqx.io:8083/mqtt', { username: 'emqx_test', password: 'emqx_test' })
mqtt.onSubscribe('/test/ss')
mqtt.onMessage((topic, message) => {
console.log(topic, message)
})
setTimeout(() => {
mqtt.onPublish({ topic: '/test/ss', payload: '測試1111' })
}, 3000);