写项目遇到一个功能,系统是基于ruo-yi开发的。
要求在navbar导航条的右侧添加一个全局的下载中心按钮,要求和系统中某个导出功能异步联立。导出时,按钮右下角出现加载小图标,导出完成,加载图表变成小红点,点击按钮消失。
处理:
因为考虑到两点:
- 这个下载中心状态的更新时间是不确定的,系统不知道用户什么时候点击的导出,短时间内多批次发送导出任务的异步处理等等。
- 系统要去识别当前登陆者的key值来确定这个用户的身份到底是谁?
PS:因为这个导出功能是选中多行信息后点击导出按钮这样一个交互,此项目中是通过联立后端接口实现的。和下载功能不同,所以此处不能像下载一样js监听浏览器下载状态来处理。所以考虑到用websocket来处理下载中心的状态更新。
解决:
网上websocket的攻略很多,大同小异,此处我大概展示一下我的代码:
(因为我只是需要websocket去更新我这个下载中心的状态值,而下载中心我已经封装成单独组件了,所以没有将websocket写成js文件,而是直接写进下载中心这个组件的父组件中了。然后通过父子组件间的值传递来控制子组件的状态更新,这样更加便于维护。)
// 父组件
data() {
return {
// websocket实例初始
websocket: null,
// 重连时间
reconnectTimer: null,
}
}
mounted() {
this.initWebsocket();
},
methods: {
initWebsocket() {
try {
// 判断浏览器是否支持WebSocket
if ('WebSocket' in window) {
// 正式环境参数
// 此处key从cookie取的; 127.0.0.1:8080我随便写的,正式用的时候需要改成你连的后端的环境地址
// 如果业务不需要websocketUrl上带参数,?key=后面都不要就行了
this.websocket = new WebSocket('ws://127.0.0.1:8080/ws?key=' + Cookies.get('userKey'));
this.mnWebSocket();
} else {
alert('当前浏览器不支持');
}
} catch (e) {
// console.log('尝试创建连接失败')
this.reConnect()
}
},
mnWebSocket() {
// 连接错误
this.websocket.onerror = this.setErrorMessage()
// 连接成功
this.websocket.onopen = this.setOnopenMessage()
// 收到消息的回调
this.websocket.onmessage = this.setOnmessageMessage()
// 连接关闭的回调
this.websocket.onclose = this.setOncloseMessage()
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = this.onbeforeunload()
},
// 连接错误
setErrorMessage(event) {
//调用重连函数
this.reConnect()
// console.log('WebSocket连接发生错误状态码:' + this.websocket.readyState, event)
},
// 连接成功
setOnopenMessage() {
let _this = this;
// console.log('WebSocket连接成功状态码:' + this.websocket.readyState)
_this.reconnectTimer = setInterval(function () {
// console.log('WebSocket发送信息:' + "心跳:" + new Date().toLocaleString())
_this.websocket.send('心跳:' + new Date().toLocaleString());
}, 6 * 1000);
},
// 接受消息的回调
setOnmessageMessage(event) {
let _this = this;
// console.log('event', event)
const dataJson = JSON.parse(JSON.stringify(event.data));
if (dataJson == 'downing') {
_this.isDownLoad = 1;
// 模拟此时文件导出完成
setTimeout(() => {
_this.isDownLoad = 2;
}, 2000)
} else if (dataJson == 'downloadFinish'){
_this.isDownLoad = 2;
}
},
// 连接关闭的回调
setOncloseMessage() {
// 重连
this.reConnect()
// console.log('WebSocket连接关闭状态码:' + this.websocket.readyState)
},
onbeforeunload() {
this.closeWebSocket()
},
closeWebSocket() {
const _this = this;
clearInterval(_this.reconnectTimer)
_this.websocket.close();
_this.websocket.onclose = function (evt) {
// console.log("websocket已关闭");
};
}
},
beforeDestroy() {
this.onbeforeunload();
}