一想到你我就呕…呕呕~~~,咳咳,跑偏了。这篇文章主要记录我在vue使用mqtt的过程,以便大家少走弯路

MQTT为何物?(各位看官,马上会有一堆废话,注意走位)
百度百科
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,基于TCP/IP;
有三种消息发布服务质量(qos):
“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
“至少一次”,确保消息到达,但消息重复可能会发生。
“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

我的理解:如果A与B要通信,其中需要一个消息中间件C(broker),无论A/B谁发布消息(理想情况是有更新时就发布),都发向C,无论谁订阅消息都向C订阅,然后不断获取到最新的A/B的消息。订阅的终端可有多个(类似,北斗只负责发位置信息,终端设备只需要获取就可以了,且是最新的)

大概这样子(嘘…菜鸟教程上偷的图):
在这里插入图片描述

提示: 你可能需要知道你的 mqtt 链接(用户名,密码,地址等)是否可用,提供两个网站

mqtt 测试网站:(推荐第二个,第一改版了,代码能连接上,它却连接不上)
MQTT WebSocket Toolkit
HiveMQ

正文


想在vue中使用,先安装:

cnpm install mqtt -S//这样默认给你安装的是4.1.0版本

总共主流版本有三个(我是jsdelivr看的, 【写文章时最新时4.1.0】其实@4.1.0是默认安装,所以它的高下载量并不代表其稳定,就像现在的4.2.6一样)
在这里插入图片描述
建议大家安装3.0.0或2.18.8,


2021年5月19日13:32:13更新

版本@3.0.0@4.2.6,当连续(for循环)发布2个以上链接时,连接成功,当时除第一个外都会发布失败(client disconnecting),我已经降版本到2.18.8!哎~~

cnpm install mqtt@3.0.0 -S

因为ie(包括以ie为内核的360急速浏览器)上不识别4.1.0版本的es6语法。我曾尝试在babel.config.js有过如下配置想转为es5.

module.exports = {
  presets: [
    ['@vue/app', {
      'polyfills': [
          'es6.promise',
          'es6.symbol'
      ],
      useBuiltIns: 'usage'  //使用usage不用安装babel/polyfill和引入
    }]
  ],
  plugins: ['@babel/plugin-transform-arrow-functions']//需要安装
}

均无果,各位可以去尝试。本人限于水平,若有大佬配置成功欢迎留言交流。

我只在一个页面用到了,所以在单页面中引入

import mqtt from "mqtt"

注意: 一个项目保持一个mqtt链接即可,不同页面可以不同的主题订阅或发布不同主题。

接着贴一下使用代码(代码中注释很全)

//引入connect配置
import { mqttConfig } from "../../commonParams/index.js"

关于配置项:

  • 端口,用户名,密码是后台约定(提供)
  • 下面我注释掉的配置项是默认配置,什么?你不信?看这MQTT.js#connect
//commonParams/index.js
export const mqttConfig = {
  port: 8083,
  // keepalive: 60,
  // clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
  // protocolId: 'MQTT',
  // protocolVersion: 4,
  // clean: true,
}

定义了两个函数:

/*
	注释中所提到的后台即为发布端/订阅端,
*/
// 初始化mqtt
  initMqtt(topic){
    const _this = this;
    //建立连接,需要搭建消息中间件服务器的(我这里是后台)提供用户名或密码
    const cfg = Object.assign(mqttConfig, {
      username: 'xxxx1',
      password: 'xxx2',
    });
    // 在data中定义MQTT,以便断开连接
    // ws://xxxxx是连接地址,后台提供,wss是https连接
    _this.MQTT = mqtt.connect('ws://xxxxx', cfg)
    _this.MQTT.on('error', (e) => {
      _this.MQTT.end();
    });
   //建立连接后订阅主题
    _this.MQTT.on('connect', () => {
      // 订阅一个主题
      _this.MQTT.subscribe(topic, { qos: 1 }, err => {
        if (!err) {
          console.info(' ---- 订阅成功')
        }else{
          console.warn('订阅失败')
        }
      })
    });
    // 后台发送的消息
    _this.MQTT.on('message', function (top, message) {
      //发送过来的如果是对象你是需要解析的。
      const res = JSON.parse(message.toString());
      const TOP = top.replace('tops/','');
      console.log(top + ': ', res);
      //根据不同主题进行赋值操作
      switch(TOP){
        case "top1":
          _this.data1 = [res];
          break;
        case "top2":
          _this.data2 = [...res];
          break;
        //其他情况
      }
    });
    // 其他异常事件
    _this.MQTT.on('reconnect', () => {
      console.info('正在重连')
    });
    _this.MQTT.on('disconnect', (error) => {
      console.info('服务器断开:', error)
    });
    _this.MQTT.on('close', () => {
      _this.MQTT.end();
    });
  },

上面你可能注意到,this.MQTT为全局变量,这是为了离开此页面时销毁mqtt链接

beforeDestroy(){
  if(this.MQTT.end) this.MQTT.end();
},
 // 发布mqtt,用户名密码和连接配置找后台要
  mqttPublish(topic){
    const _this = this;
    const cfg = Object.assign(mqttConfig, {
      username: 'xxx2',
      password: 'xxxx',
    });
    _this.MQTT = mqtt.connect('ws://xxxx', cfg)
    _this.MQTT.on('connect', (e) => {
    	//建立连接后就发布就行了,主题和后台约定。
    	//还有qos,就是开头提到的消息发布服务质量。
      _this.MQTT.publish(topic,JSON.stringify(_this.publicMSG), { qos: 1 }, error => {
        if (!error) {
          this.MQTT.end();
        }else{
          console.warn('发布失败')
        }
      })
    });
  },

然后调用就好了

created(){
    /*
      + 通配一层(tops/x,top/x1),
      # 通配0~多层(tops/x, tops/,tops/x/x/x)
      当有多个主题是,前面分个一级主题(tops)比较适合后面跟+号就所有 tops/ 开头都能订阅了
    */ 
    this.initMqtt('tops/+');
  },

需要发布时:

//注意后台订阅的时候一级主题也是tops,你们约定就行
this.mqttPublish('tops/top3')

以上。
予人玫瑰,手留余香~~~,

Logo

前往低代码交流专区

更多推荐