vue使用websocket以及附带封装源码
Sonder
2023-03-10
4630字
12分钟
浏览 (2.8k)
概念
WebSocket的定义
WebSocket是html5提供的一种在单个TCP连接上进行双向通信的协议,解决了客户端和服务端之间的实时通信问题。浏览器和服务器只需完成一次握手,两者之间就可以创建一个持久性的TCP连接,此后服务器和客户端通过此TCP连接进行双向实时通信。
WebSocket的优点
很多网站为了实现数据推送,所用的技术都是ajax轮询。轮询是在特定的时间间隔,由浏览器主动发起请求,将服务器的数据拉回来。轮询需要不断的向服务器发送请求,会占用很多带宽和服务器资源。WebSocket建立TCP连接后,服务器可以主动给客户端传递数据,能够更好的节省服务器资源和带宽,实现更实时的数据通讯。
使用ws
引入
import websocket from "@/common/websockets";
发送ws
sendMessage(){
let type = 1;
let data = {
url: 213123
}
websocket.request(type,data)
},
初始化并调用ws
initMeeting(){
websocket.initWebsocket(
202303112000001,
this.dealWithCallback,
{
role:21312321,
is_test:111,
watch:222,
openid:this.$route.query.openid || this.$tools.getCookie('openid')
}
)
},
dealWithCallback(res){
console.log(`res===>`, res)
},
封装代码
const config = {
websocketHost: 'ws://xxx.xxx.com/ws'
}
const websocket = {
host:"",
container:null,
meet:{
id:'', // 会议id
receive:null, // 回调函数
params:{}
},
// 重连属性
connect:{
lock:false, // 加锁,重连期间,不重复链接
time:2, // 重连时间,目前每2秒重连一次
count:15, // 允许最大重连次数
currentNumner:0, // 当前重连次数
close:false // 是否关闭
},
// 重连定时器
timer:{
time:null,
startTime:0
},
heart:{
time:null,
startTime:0,
activity:false,
ping:10
}
}
// 初始化websocket
const initWebsocket = (meetId,receive,params) => {
websocket.url = `${config.websocketHost}/${meetId}`;
websocket.meet.id = meetId
websocket.meet.receive = receive
websocket.meet.params = params
console.log( websocket.meet.params )
websocket.container = new WebSocket(websocket.url)
let needReConnect = true; // 报错是否需要重连
websocket.container.onopen = () => {
// 每次重连,取消锁
websocket.connect.lock = false;
this.$store.store.dispatch("setItem",{isConnect:true})
clearWebSocketTime("timer");
websocketRequest("meet_login",{...websocket.meet.params});
webSocketHeart()
}
websocket.container.onmessage = (res) => {
websocket.meet.receive && websocket.meet.receive(JSON.parse(res.data));
}
websocket.container.onerror = (err) => {
if(needReConnect) {
websocket.connect.lock = false;
needReConnect = false;
reConnectWebsocket();
}
console.error("websocket connect is error",err);
}
websocket.container.onclose = (err) => {
console.error("websocket connect is close",err);
if(err.type == 'login_failed') return;
if(needReConnect) {
websocket.connect.lock = false;
needReConnect = false;
reConnectWebsocket();
}
}
}
const clearWebSocketTime = (key) => {
websocket[key].startTime = 0;
if(websocket[key].time) {
clearTimeout(websocket[key].time);
websocket[key].time = null;
}
}
// 重连服务端
const reConnectWebsocket = () =>{
if(websocket.connect.close || websocket.connect.lock) return;
// if(websocket.connect.lock) return;
console.log("reconnecting......")
websocket.connect.lock = true;
this.$store.store.dispatch("setItem",{isConnect:false})
websocket.connect.currentNumner += 1;
clearWebSocketTime("timer");
// 判断是否达到重连最多次数
if(websocket.connect.currentNumner > websocket.connect.count){
console.log("重连失败,请刷新重试")
return;
}
websocket.timer.startTime = Date.now();
websocket.timer.time = setTimeout(()=>{
initWebsocket(websocket.meet.id,websocket.meet.receive,websocket.meet.params);
},websocket.connect.time * 1000);
}
// 心跳
const webSocketHeart = () => {
clearWebSocketTime("heart")
if(websocket.heart.activity) return;
websocket.heart.startTime = Date.now();
websocket.heart.activity = true;
websocket.heart.time = setTimeout(()=>{
websocket.heart.activity = false
websocketRequest("meet_ping",{})
webSocketHeart()
},websocket.heart.ping * 1000);
}
// 发送消息
const sendMessage = (data) => {
if(!websocket.container) {
console.error("websocket is not connect!")
return;
}
if(data.type !== "meet_ping") console.log(data)
websocket.container.send(JSON.stringify(data));
}
// 发送websocket请求
const websocketRequest = (type,data) => {
sendMessage({
type,
data
})
}
// 关闭websocket
const websocketClose = () => {
websocket.container && websocket.container.close()
websocket.connect.close = true;
setTimeout(()=>{ websocket.connect.close = false;},2000)
websocket.container = null;
}
export default {
request:websocketRequest,
initWebsocket,
sendMessage,
close:websocketClose
}