阅读 1186

Vue项目使用WebSocket技术

【基础】为什么使用WebSocket?

​前端和后端的交互模式最常见的就是前端发数据请求,后端响应传输数据之前端进行展示。如果前端不操作,后端不能主动向前端推送数据。 ​因此,在业务场景需服务端主动向客户端推送消息,同时客户端也可以主动向服务端发送消息时,那就有了WebSocket的用武之地。

【特点】WebSocket的特点如下:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

【注意点】在Vue使用WebSocket需注意以下几点:

(1)当前浏览器对WebSocket的兼容性如下:兼容性

(2)在组件加载的时候连接websocket,在组件销毁的时候断开websocket

(3)后端接口需要引入socket模块,否则不能实现连接。

1.基础版

1.0 原生WebSocket基本介绍

事件
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
方法
Socket.send()使用连接发送数据
Socket.close()关闭连接
属性
readyState 只读属性表示连接状态
bufferedAmount 只读属性已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数

1.1代码分析(当前版本包含心跳机制)

<script>
	export default {
		components: { VueQr },
		data() {
			return {
				lockReconnect: false, //是否真正建立连接
				timeout: 58 * 1000, //58秒一次心跳
				timeoutObj: null, //心跳心跳倒计时
				serverTimeoutObj: null, //心跳倒计时
				timeoutnum: null, //断开 重连倒计时
			};
		},
		created() {
			this.initWebSocket();
		},
		destroyed() {
			this.websock.close(); //离开路由之后断开websocket连接
		},
		methods: {
			currentTime() {
				setInterval(this.formatDate, 500);
			},
			initWebSocket() {
				//初始化weosocket
				const wsuri = "wss://xxxxxxx/xx/xx/" + this.roomId;
				this.websock = new WebSocket(wsuri);
				// 客户端接收服务端数据时触发
				this.websock.onmessage = this.websocketonmessage;
				// 连接建立时触发
				this.websock.onopen = this.websocketonopen;
				// 通信发生错误时触发
				this.websock.onerror = this.websocketonerror;
				// 连接关闭时触发
				this.websock.onclose = this.websocketclose;
			},
			// 连接建立时触发
			websocketonopen() {
				//开启心跳
				this.start();
				//连接建立之后执行send方法发送数据
				// let actions = {"room":"007854ce7b93476487c7ca8826d17eba","info":"1121212"};
				// this.websocketsend(JSON.stringify(actions));
			},
			// 通信发生错误时触发
			websocketonerror() {
				console.log("出现错误");
				this.reconnect();
			},
			// 客户端接收服务端数据时触发
			websocketonmessage(e) {
				console.log(e.data);
				//收到服务器信息,心跳重置
				this.reset();
			},
			websocketsend(Data) {
				//数据发送
				this.websock.send(Data);
			},
			// 连接关闭时触发
			websocketclose(e) {
				//关闭
				console.log("断开连接", e);
				//重连
				this.reconnect();
			},
			reconnect() {
				//重新连接
				var that = this;
				if (that.lockReconnect) {
					return;
				}
				that.lockReconnect = true;
				//没连接上会一直重连,设置延迟避免请求过多
				that.timeoutnum && clearTimeout(that.timeoutnum);
				that.timeoutnum = setTimeout(function () {
					//新连接
					that.initWebSocket();
					that.lockReconnect = false;
				}, 5000);
			},
			reset() {
				//重置心跳
				var that = this;
				//清除时间
				clearTimeout(that.timeoutObj);
				clearTimeout(that.serverTimeoutObj);
				//重启心跳
				that.start();
			},
			start() {
				//开启心跳
				console.log("开启心跳");
				var self = this;
				self.timeoutObj && clearTimeout(self.timeoutObj);
				self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
				self.timeoutObj = setTimeout(function () {
					//这里发送一个心跳,后端收到后,返回一个心跳消息,
					if (self.ws.readyState == 1) {
						//如果连接正常
						// self.ws.send("heartCheck"); //这里可以自己跟后端约定
					} else {
						//否则重连
						self.reconnect();
					}
					self.serverTimeoutObj = setTimeout(function () {
						//超时关闭
						self.ws.close();
					}, self.timeout);
				}, self.timeout);
			},
		},
		mounted() {
			this.currentTime();
		},
		// 销毁定时器
		beforeDestroy() {
			if (this.formatDate) {
				clearInterval(this.formatDate); // 在Vue实例销毁前,清除时间定时器
			}
		},
	};
</script>
复制代码
文章分类
前端
文章标签