vue项目使用sockjs实现长连接

一、安装sockjs-client包、stompjs包

npm install sockjs-client stompjs -save

二、sock.js文件

        我的项目中使用vuex封装sock.js文件

import Vue from 'vue'
import Vuex from 'vuex'
import SockJS from "sockjs-client";
import Stomp from "stompjs";
import {getAccessToken} from '@/utils/auth'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    url:`${process.env.VUE_APP_BASE_API}/sockjs/?1access_token=${getAccessToken()}`,// token通过url携带
    checkInterval:null,//断线重连时 检测连接是否建立成功
    websocket:null,
    stompClient:null, // stomp客户端对象
    listenerList:[],//监听器列表,断线重连时 用于重新注册监听
  },
  getters: {
    stompClient(state) {
      return function () {
        return state.stompClient;
      }
    }
  },
  mutations: {
    WEBSOCKET_INIT(state,url) { // 初始化连接
      if(state.stompClient==null||!state.stompClient.connected) {
        if(url) state.url = url
        if(state.stompClient!=null&&state.websocket.readyState=== SockJS.OPEN){ // 如果读取状态为open 断开连接后重新连接
          state.stompClient.disconnect(()=>{
            this.commit('WEBSOCKET_CONNECT')
          })
        }else if(state.stompClient!=null&&state.websocket.readyState=== SockJS.CONNECTING){ // 连接已建立
          console.log("已连接")
          return;
        }else{ //
          console.log("连接正在建立2")
          this.commit('WEBSOCKET_CONNECT')
        }
        if(!state.checkInterval){ // 使用定时器进行循环访问建立连接
          const interval=setInterval(()=>{
            console.log("检测连接:"+state.websocket.readyState ,SockJS.CONNECTING)
            if(state.stompClient!=null&&state.stompClient.connected){
              clearInterval(state.checkInterval)
              state.checkInterval=null
              console.log('重连成功')
            }else if(state.stompClient!=null&&state.websocket.readyState !== SockJS.CONNECTING){
              //经常会遇到websocket的状态为open 但是stompClient的状态却是未连接状态,故此处需要把连接断掉 然后重连
              state.stompClient.disconnect(()=>{
                this.commit('WEBSOCKET_CONNECT')
              })
            }
          },2000)
          state.checkInterval=interval
        }
      }else{
        console.log("连接已建立成功,不再执行")
      }
    },
    WEBSOCKET_CONNECT(state){ // 具体连接代码
      try {
        const _this = this
        const websock = new SockJS(state.url);
        state.websocket=websock
        // 获取STOMP子协议的客户端对象
        const stompClient = Stomp.over(websock);
        stompClient.debug = null //关闭控制台打印
        stompClient.heartbeat.outgoing = 20000;
        stompClient.heartbeat.incoming = 0;//客户端不从服务端接收心跳包
        // 向服务器发起websocket连接
        console.log(state,'~~~~~~~~',stompClient)

        stompClient.connect(
          {
            // Authorization:`Bearer ${getAccessToken()}` // token也可在此处添加
          },  //此处注意更换自己的用户名,最好以参数形式带入
          frame => {// stomp连接成功回调
            state.listenerList.forEach(item=>{
              state.stompClient.subscribe(item.topic,item.callback)
              console.log(state.stompClient.subscribe,'+++++++++++')
            })
            //unsubscribe()可以用来取消客户端对这个目的地destination的订阅
            // stompClient.subscribe("/user/queue/message", msg => {
            //   // this.getData(msg);
            //   console.log(msg)
            // });
          },
          err => {//第一次连接失败和连接后断开连接都会调用这个函数 此处调用重连
            setTimeout(() => {
              console.log(err,'errrrrr')
              _this.commit('WEBSOCKET_INIT', state.url)
            }, 1000)
          },

        );
        state.stompClient = stompClient
      }catch (e) {
        console.log(e,'err')
      }
    },
    WEBSOCKET_SEND(state, p) { // 发送消息
      state.stompClient.send(p.topic,{},p.data);
    },
    WEBSOCKET_UNSUBSRCIBE(state,p){ // 断开连接
      state.stompClient.unsubscribe(p)
      for(let i=0;i<state.listenerList.length;i++){
        if(state.listenerList[i].topic==p){
          state.listenerList.splice(i,1)
          console.log("解除订阅:"+p+" size:"+state.listenerList.length)
          break;
        }
      }

    }
  },
  actions: {
    WEBSOCKET_INIT({commit},url) {
      commit('WEBSOCKET_INIT',url)
    },
    WEBSOCKET_SEND({commit}, p) {
      commit('WEBSOCKET_SEND', p)
    },
    WEBSOCKET_UNSUBSRCIBE({commit}, p){
      commit('WEBSOCKET_UNSUBSRCIBE', p)
    }
  }
})

三、main.js中为vue全局挂载$webscoket方法以便组件使用

import websocket from './store/soket'
Vue.prototype.$websocket = websocket;

四、组件引用

  mounted(){
    this.$websocket.state.stompClient.subscribe('/work/update',res=>{
      // 订阅消息 处理逻辑
    })
  },
  beforeDestroy() {
    // 组件销毁 断开连接
    this.$websocket.state.stompClient.unsubscribe('/work/update')
  },

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值