vue使用websocket连接
前景
公司做一个包含websocket的项目 ,我用的是vue做的 ,开始只有一个组件的要求demo ,就将websocket的配置直接放在组件方法中 ,组件挂载时直接初始化ws ,但是后续组件增加 ,开始出现多个websocket链接的情况 ,是不允许的 。
刚开始的做法是将websocket的方法配置等封装为一个js文件给各个组件调用 ,当离开组件页面进入新页面时会断连旧的ws新建一个ws ,以为做到了独立 ,但是实际上确实多次的断连链接 ,十分不便 。
思考了挺久找到了解决方法 ,在此记录加深记忆
解决过程
要求整个vue项目使用一个ws链接,在各组件都要求可以接受发送消息
首先想到的就是在app.vue下创建我是链接 ,然后给各个小的组件使用ws ,做到统一,很简单的解决思路 ,我是这么做的
前期已经将ws封装成一个wsconnect.js文件了 ,那么是否可以将wsconnect注册为全局的方法呢 ,试了一下果真可行 ,只需要在main.js中配置:
import wsConnect from "@/assets/js/wsConnect";
Vue.prototype.$ws = wsConnect
new Vue({
render: h => h(App),
router,
axios,
store
}).$mount(#app)
说明一下 ,在wsconnect.js文件中我封装了方法 ,但是把ws对象放在了vuex的state中 ,相关配置如下:
wsconnect.js:
import axios from "axios";
import store from "@/store";
//websocket
function initWebpack(){
var url = store.state.url
var wsurl =
axios.get(`${url}/bcall/url`) //这是我在从后端拿ws链接的地址
.then((res) => {
console.log(res.data.data)
wsurl = res.data.data
store.state.ws = new WebSocket(wsurl);
store.state.ws.onopen = onopen;
store.state.ws.onmessage = onmessage;
store.state.ws.onclose = onclose;
store.state.ws.onerror = onerror;
}).catch((err)=> {
console.log(err)
})
}
function onopen() {
console.log("连接websocket");
var params = {"reqtype":"Query","action":"allexts"}
store.state.ws.send(params)
start();
}
function reconnect() {//重新连接
var that = store.state;
if(that.lockReconnect) {
return;
}
that.lockReconnect = true;
//没连接上会一直重连 ,设置延迟避免请求过多
that.timeoutnum && clearTimeout(that.timeoutnum);
that.timeoutnum = setTimeout(function () {
//新连接
initWebpack();
that.lockReconnect = false;
that.isFirstGet = true
},5000);
}
function reset(){//重置心跳
var that = store.state;
//清除时间
clearTimeout(that.timeoutObj);
clearTimeout(that.serverTimeoutObj);
//重启心跳
start();
}
function start(){ //开启心跳
console.log(开启心跳);
var self = store.state;
self.timeoutObj && clearTimeout(self.timeoutObj);
self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
self.timeoutObj = setTimeout(function(){
//这里发送一个心跳 ,后端收到后 ,返回一个心跳消息 ,
if (self.ws.readyState === 1) {//如果连接正常
self.ws.send(heartbeat); //心跳包格式需要自己确定
}else{//否则重连
reconnect();
}
self.serverTimeoutObj = setTimeout(function() {
//超时关闭
self.ws.close();
reconnect()
}, self.timeout);
}, self.timeout)
}
function onmessage(e) {
console.log(接收数据,e)
//处理数据的地方
reset();
}
function onclose(e) {
console.log(websocket 断开: ,e);
}
function onerror(e) {
console.log("出现错误");
//重连
reconnect();
}
export default {
initWebpack,
onmessage,
onclose,
onopen,
onerror
}
store.state:
state: {
permissions: false,
url: ,
//ws参数
path: ,
ws: null,//建立的连接
lockReconnect: false,//是否真正建立连接
timeout: 58*1000,//58秒一次心跳
timeoutObj: null,//心跳心跳倒计时
serverTimeoutObj: null,//心跳倒计时
timeoutnum: null,//断开 重连倒计时
},
配置之后我在app.vue挂载之后直接初始化ws链接:
mounted() {
this.$ws.initWebpack()
}
发现是成功的 ,已经将ws链接上了,接着就是在各个组件测试一下发送数据的功能:
this.$store.state.ws.send(msg)
神奇的发现 ,也成功了!
之所以这么简单 ,前期的封装也是占功劳的嘛,至此我的vue只需要一个ws链接就可以供整个项目使用 ,虽然不知道别人的做法是怎么样 ,如果有更好的方法也希望大家讲解下
vue2全局使用websocket记录
1 、考虑到登录之后要始终连接服务器接收消息 ,所以把websocket实例对象作为模块抛出 ,在main.js中引入 ,使全局都可以获得ws并且使用相关方法 。
2 、由于刷新页面时 ,ws会自动断开连接 ,所以在App.vue组件挂载时再次连接服务器 。
新建ws模块文件
该文件位置任意 ,引入的时候注意路径即可
export default {
ws: {},
setWs: function(newWs) {
this.ws = newWs
},
start(){// 发送心跳
clearInterval(this.timeoutObj)
this.timeoutObj = setInterval(() => {
if (this.ws && this.ws.readyState == 1) {
console.log(发送心跳)
this.ws.send(JSON.stringify({
//后端需要接收的数据
}));
}
}, 10 *1000)//十秒发一次
},
localSocket(userId) {//连接ws ,根据连接服务器是否需要参数设置该方法是否需要接收参数
if ("WebSocket" in window) {
// console.log("您的浏览器支持 WebSocket!");
// location.host
this.ws = new WebSocket(这里要填连接服务器的地址);
this.setWs(this.ws);
this.ws.onopen = ()=>{
console.log(websocket连接成功);
//连接上之后要发心跳包
this.start()
};
this.ws.onclose = function () {
// 关闭 websocket
console.log("连接已关闭...");
//断线重新连接
setTimeout(() => {
this.localSocket(userId);
}, 2000);
};
} else {
// 浏览器不支持 WebSocket
console.log("您的浏览器不支持 WebSocket!");
this.openNotificationWithIcon(error, 浏览器, 您的浏览器不支持显示消息请更换, 1,1)
}
},
}
在main.js中引用ws模块文件
import global from ./ws.js
Vue.prototype.global = global
App.vue挂载时再次连接服务器并且接收消息
mounted(){
this.global.localSocket(userId)
//连上之后要接收服务器发来的消息
this.global.ws.onmessage = (msg)=>{
console.log(JSON.parse(msg.data))
}
}
通过以上方法 ,任何组件都可以通过this.global.ws获得websocket实例对象并且使用相关方法 ,可能会有些问题 ,但是我别的问题太多了,这个先放一下吧 。
以上为个人经验 ,希望能给大家一个参考 ,也希望大家多多支持本站 。
声明:本站所有文章,如无特殊说明或标注 ,均为本站原创发布 。任何个人或组织 ,在未征得本站同意时 ,禁止复制 、盗用 、采集 、发布本站内容到任何网站 、书籍等各类媒体平台 。如若本站内容侵犯了原著者的合法权益 ,可联系我们进行处理 。