【vuex + websocket】前端封装websocket进行长连接

前提:需求需要利用websocket进行前后端传讯
请注意:向服务器发送消息方法待校验

一些特殊事项

  1. 在vuex使用this,需要在调用actions 时传入this指针
    this.connectWebsocket(this)
    在actions 中重新赋值
connectWebsocket({ commit, rootState }, _this) {
	...
	// 赋值this
	state._this = _this
}
  1. 在vuex内调用其他模块的state
connectWebsocket({ commit, rootState }, _this) {
	...
	// 获取vuex另一个模块的state
	const userInfo = rootState.user.userInfo
}

Vuex封装websocket

后端返回的数据格式
data='{msgType: xxx', data: {...}}'

文件夹内
|- store
|----modules
|-------websocket.js
|----index.js
|----getters.js

websocket.js

const state = {
    url: 'http://127.0.0.1:80/websocket/', //后端提供的链接路径
    ws: null,
    wsMessage: null,
    _this: null
}

const mutations = {
    CONNECT_WEBSOCKET: (state, data) => {
        state.wsMessage = data.includes('msgType') ? JSON.parse(data) : data
    }
}

const actions = {
    connectWebsocket({ commit, rootState }, _this) {
    	// 赋值this
        state._this = _this
        if (!('WebSocket' in window)) {
            _this.msgError('您的浏览器不支持WebSocket');
            return;
        }
        // 获取vuex另一个模块的state
        const userInfo = rootState.user.userInfo
        // 将http协议名替换为 ws://
        state.url = state.url.replace('http', 'ws')
        state.ws = new WebSocket(state.url + '?userId=' + userInfo.userId);
        state.ws.onopen = function(event) {
            console.log('**********************连接开始**********************')
        };
        state.ws.onmessage = function(event) {
            commit('CONNECT_WEBSOCKET', event.data)
            console.log('**********************连接接收**********************')
        };
        state.ws.onclose = function(event) {
            console.log('**********************连接关闭**********************')
        };
        state.ws.onerror = function(event) {
            console.log('**********************连接异常**********************')
            _this.msgError('连接异常!')
        };
    },
    // 关闭websocket连接
    closeWebsocket({ commit }, userId) {
        if (state.ws) {
            state.ws.close();
            state.ws = null;
        }
    },
    // 向服务器发送消息
    sendWebsocket({ commit }, message) {
        if (!state.ws || state.ws.readyState !== 1) {
            state._this.msgError('未连接到服务器');
            return;
        }
        if (!message) {
            state._this.msgError('请输入发送内容');
            return;
        }
        state.ws.send(message);
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

getters.js

const getters = {
  wsMessage: state => state.websocket.wsMessage
}
export default getters

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import websocket from '@/store/modules/websocket'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    websocket
  },
  getters
})

export default store

main.js

import store from './store';

文件内调用

...
    computed: {
      ...mapState({
        wsMessage: state => state.websocket.wsMessage
      })
    },
   	watch: {
   	// 监听websocket返回的数据
      wsMessage: {
        deep: true,
        handler(val) {
          if (val && val.msgType == 'excelTask') {
            this.msgError('文件导出中……')
            const data = val.data
            if (data.status == 3) {
              this.msgError('文件导出失败!')
            } else {
              downloadFileUrl(data.fileUrl, data.fileName).then(() => {
                this.msgSuccess('文件导出成功!')
              });
            }
            // 调用关闭连接
            this.closeWebsocket();
          }
        }
      }
    },
     methods: {
     // 获取vuex actions
     ...mapActions({
        connectWebsocket: 'websocket/connectWebsocket',
        closeWebsocket: 'websocket/closeWebsocket'
      }),
	  // 导出
      handleExport() {
      	// 连接websocket 并传入this指针
      	this.connectWebsocket(this)
      	this.$confirm('确认导出?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'primary'
        }).then(() => {
          export({}).catch(() => {
            this.msgError('导出失败!')
          })
        }).catch(() => {
          this.closeWebsocket();
        }
      }
     }
...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值