赞
踩
服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
连接:
const ws = new Wenscoket('ws://xxxx')
这样就就会创建ws实例并且客户端就会与服务器进行连接。
ws.onopen=()=>{} //连接成功之后的监听
ws.onclose=()=>{} //连接失败或者关闭的回调
ws.onmessage=(data)=>{} //监听后端发送的信息
ws.onerror = ()=>{} //出错之后的回调。
ws.send(data)//向后端发送信息。
const WebSocket = require("ws"); const path = require("path"); const wss = new WebSocket.Server({. //新建实例 port: 9998, }); wss.on("connection", (client) => { //开启服务 client.on("message", async (msg) => { //监听前端的发送数据,msg为前端发送回来 client.send(JSON.stringify(payload)); //向后端发送数据 //所有客户端 wss.clients,向所有连接客户端发送数据 wss.clients.forEach((item) => { item.send(msg); }); } }); });
interface WebSocketDataParams { socketType: string; action: string; chartName: string; value: boolean; } interface WebSocketDataProps { socketType: string; action: string; chartName: string; value: boolean; data: string; } class SocketService { /** * 单例 保证拿到的都是同一个实例 */ static instance: SocketService; static get Instance() { if (!this.instance) { this.instance = new SocketService(); } return this.instance; } baseUrl: string; ws: WebSocket; callBackMapping: Record<string, any>; isconnect: boolean; sendRetryCount: number; //重复发送次数 connectRetryCount: number; constructor(url: string = "ws://localhost:9998") { this.baseUrl = url; this.ws = {} as WebSocket; this.callBackMapping = {}; this.isconnect = false; this.sendRetryCount = 0; this.connectRetryCount = 0; } //和服务端创建的stocket对象 //定义连接服务器的方法 connect(url = "") { if (!window.WebSocket) { return console.log("您的浏览器不支持WebSocket"); } url = url ? url : this.baseUrl; this.ws = new WebSocket(url); //连接监听 this.ws.onopen = () => { console.log("连接服务端成功"); this.connectRetryCount = 0; this.isconnect = true; }; this.ws.onclose = () => { this.connectRetryCount++; console.log("连接失败/关闭"); this.isconnect = false; //当连接关闭后进行重新连接尝试 setTimeout(() => { this.connect(); }, this.connectRetryCount * 500); }; this.ws.onmessage = (res) => { const recvData: WebSocketDataProps = JSON.parse(res.data); const stocketType = recvData.socketType; //与后端约定type //如果存在,直接调用 const callBack = this.callBackMapping[stocketType]; //执行订阅的回调 if (callBack) { const action = recvData.action; if (action === "getData") { const realData = JSON.parse(recvData.data); //将数据传给回调函数 callBack.call(this, realData); } else if (action === "fullScreen") { } else if (action === "themeChange") { } } }; } //注册回调函数,可能有多个scoket registerCallBack( socketType: string, callBack: (data: Record<string, any>) => void ) { this.callBackMapping[socketType] = callBack; } unRegisterCallBack(socketType: string) { this.callBackMapping[socketType] = null; } send(data: WebSocketDataParams) { if (this.isconnect) { this.sendRetryCount = 0; //发送成功重置为0 this.ws.send(JSON.stringify(data)); } else { setTimeout(() => { this.sendRetryCount++; this.send(data); }, this.sendRetryCount * 500); } } } const wss = SocketService.Instance; export { wss };
采用封装类,然后可能会有多个页面需要使用到,所以采用派发订阅的模式
监听到数据的时候拿到对应的订阅函数执行。
如,注册,然后记得注销掉。
这样一监听到后端返回来的数据就会执行回应的回调函数。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。