需求是獲取導出記錄。特點,無論哪個路由都能訪問記錄;進行導出操作時,等待后台處理后會通過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
流程是建立連接——綁定賬號(省略)——進行了導出操作后,待后台處理完畢后會發送數據過來,這時候前端就負責彈出這個下載框
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()
}
};