綜合 |vuex與websoket應用


需求是獲取導出記錄。特點,無論哪個路由都能訪問記錄;進行導出操作時,等待后台處理后會通過websocket傳來下載數據並重新渲染記錄

效果

效果

vuex

import { getExportLogs } from "@/api/login";

const store = new Vuex.Store({
  //全局狀態
  state: {
    logs:[],//導出記錄
  },
    
  getters: {
    logs:state=>state.logs,
  },
  
  //改變狀態
  mutations:{
    SET_LOGS(state, val) {
        state.logs = val;
    },
  },
  
  //異步事件
  actions:{
   _getLogs({ commit }) {
    return new Promise((resolve, reject) => {
      getExportLogs()//調用函數-獲取導出記錄
        .then(res => {
          if (res.msg == 'ok') { 
            commit("SET_LOGS", res.data);//調用成功時重置狀態
            resolve(res.data);//傳出導出記錄數據
          } 
        .catch(error => {
          reject(error);
        });
    });
  }
    
})



掛載時調用:導出記錄我做成了一個組件,鑲嵌在頁面的頭部組件里。這里是指導出記錄的組件掛載時

import { mapGetters } from 'vuex'

export default{
	async mounted(){
	    this.$store.dispatch("user/_getLogs")
	},
	
	//以便數據更新時視圖能實時渲染
	computed: {
	    ...mapGetters([
	        'logs',
	    ])
	},
}

websocket

流程是建立連接——綁定賬號(省略)——進行了導出操作后,待后台處理完畢后會發送數據過來,這時候前端就負責彈出這個下載框

心跳檢測參考:https://www.jianshu.com/p/1141dcf6de3e

import store from "@/store/index";
import { Message } from "element-ui";

export default function initWebsocket() {
    //心跳檢測,每28秒發送一次信息,防止斷開連接
    var heartCheck = {
        timeout: 28000,
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function(){
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
        },
        start: function(){
            var self = this;
            this.timeoutObj = setTimeout(function(){
                //這里發送一個心跳,后端收到后,返回一個心跳消息,
                //onmessage拿到返回的心跳就說明連接正常
                ws.send("HeartBeat");
                self.serverTimeoutObj = setTimeout(function(){//如果超過一定時間還沒重置,說明后端主動斷開了
                    ws.close();     //如果onclose會執行reconnect,我們執行ws.close()就行了.如果直接執行reconnect 會觸發onclose導致重連兩次
                }, self.timeout)
            }, this.timeout)
        }
    }

    var lockReconnect = false;  //避免ws重復連接
    var ws = null;          // 判斷當前瀏覽器是否支持WebSocket
    var wsUrl = "ws://url"
    createWebSocket(wsUrl);   //連接ws

    //創建websocket
    function createWebSocket(url) {
        try{
            if('WebSocket' in window){
                ws = new WebSocket(url);
            }else if('MozWebSocket' in window){  
                ws = new MozWebSocket(url);
            }else{
                layui.use(['layer'],function(){
                  var layer = layui.layer;
                  layer.alert("您的瀏覽器不支持websocket協議,建議使用新版谷歌、火狐等瀏覽器,請勿使用IE10以下瀏覽器,360瀏覽器請使用極速模式,不要使用兼容模式!"); 
                });
            }
            initEventHandle();
        }catch(e){
            reconnect(url);
            console.log(e);
        }     
    }
	
    //回調處理
    function initEventHandle() {
        // 成功連接
        ws.onopen = function () {
            heartCheck.reset().start();      //心跳檢測重置
            console.log("連接成功"+new Date().toUTCString());
        };
        
        // 接收信息
        ws.onmessage = async function (event) {    //如果獲取到消息,心跳檢測重置
            heartCheck.reset().start();      //拿到任何消息都說明當前連接是正常的
            
            // 獲取數據
            let data=JSON.parse(event.data)
            // 彈出下載框
            if(data.type=='down_excel'){
                openDownloadDialog(data.url,data.file_name)
            }
            
        }
            
        ws.onclose = function () {
            reconnect(wsUrl);
            console.log("連接關閉!"+new Date().toUTCString());
        };
            
        ws.onerror = function () {
            reconnect(wsUrl);
            console.log("連接錯誤!");
        };
    }

    function reconnect(url) {
        if(lockReconnect) return;
        lockReconnect = true;
        setTimeout(function () {     //沒連接上會一直重連,設置延遲避免請求過多
            createWebSocket(url);
            lockReconnect = false;
        }, 2000);
    }

    //彈框-接受到websocket傳過來的下載數據時才會調用該函數
    function openDownloadDialog(url, saveName){
        //調用函數就說明后台已經異步處理完導出了,這時候派發事件重新渲染導出記錄
        store.dispatch("_getLogs")
        window.open(url);
        Message.success('導出成功!')
    }
}

建立連接

App.vue

import initWebsocket from '@/utils/createWebSocket'
export default {
  name: "App",
  mounted(){
    initWebsocket()
  }
};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM