webSocket通信封装 一. js使用WebSocket介绍 二. webSocket js封装使用 三. js封装代码 一. js使用WebSocket介绍 1. 创建WebSocket实例 url:url之前需添加ws://(未加密)或wss://(已加密),类似http://、https:// protocol:与服务端定义的协议名称相同,协议的参数例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定义协议 var ws = new WebSocket('ws://url'); var ws1 = new WebSocket('ws://url', 'myprotocol'); var ws2 = new WebSocket('ws://url', ['protocol_1','protovol_2'])); 1 2 3 2.属性 ①readyState属性:WebSocket当前连接状态 属性值 属性常量 描述 0 CONNECTING 正在与服务端建立WebSocket连接,还没有连接成功 1 OPEN 连接成功并打开,可以发送消息 2 CLOSING 进行关闭连接的操作,且尚未关闭 3 CLOSE 连接已关闭或不能打开 通过 ws.readyState属性查看当前连接状态 alert('ws连接状态:' + ws.readyState); 1 ②bufferedAmount:检查传输数据的大小,当客户端传输大量数据时使用避免网络饱和 ③protocol:在构造函数中使用,protocol参数让服务端知道客户端使用的WebSocket协议。而WebSocket对象的这个属性就是指的最终服务端确定下来的协议名称,可以为空 3. 方法 ①发送数据:send() ②关闭连接:closed() //发送数据 var message = { id: 1, title: '发送ws数据' } ws.send(JSON.stringify(message)); // 复杂的数据结构要先进行序列化 //关闭连接 ws.close() 4. 事件 WebSocket API是纯事件驱动,建立连接之后,可自动发送状态改变的数据和通知 事件值 描述 onopen 当建立websocket连接时触发,只触发一次 onerror 当连接出现错误时触发-因为当触发了onerror之后连接就会触发关闭事件 onmessage 当服务端发送数据时触发,可多次触发,页面数据展示处理模块–实现轮询 onclose 当websocket连接关闭时触发,只触发一次 使用示例 var ws = new WebSocket('ws://url'); // 获取连接状态 console.log('ws连接状态:' + ws.readyState); //监听是否连接成功 ws.onopen = function () { console.log('ws连接状态:' + ws.readyState); //连接成功则发送一个数据 ws.send('test1'); } // 接听服务器发回的信息并处理展示 ws.onmessage = function (data) { console.log('接收到来自服务器的消息:'); console.log(data); //完成通信后关闭WebSocket连接 ws.close(); } // 监听连接关闭事件 ws.onclose = function () { // 监听整个过程中websocket的状态 console.log('ws连接状态:' + ws.readyState); } // 监听并处理error事件 ws.onerror = function (error) { console.log(error); } 二. webSocket js封装使用 创建一个js文件, 代码在下, 最后将方法暴露出去, 使用的时候可以直接引用文件中的方法 调用, 或者 将该js文件挂载在vue的prototype中 直接引用文件 方法 调用 import {createWebSocket} from '@/utils/socket’ createWebSocket() 挂载在vue的prototype中 3. 整个项目只有一条webSocket通信: ① 在登录后即可创建webSocket通信, 接受的数据中可定义一个参数, 该参数来控制是 做什么功能 例如这里 : “webSocket_device_transport” 是某一个界面需要实时添加的一些数据 “webSocket_device_alarm” 是一个全局提示弹框, 需要添加的数据 ② 创建了 new Map(); key和value 用来一一对应发送和接受的数据 //思路 var globalCallback = new Map(); //创建 new Map() globalCallback.set(key,callback); //发送数据的时候, 要定义一个唯一的key 和后端返回的key是一一对应, 定义一个回调函数用来接收数据后处理数据 //例如上图片中 接收的数据 res.method == "webSocket_device_transport", 用sn作为唯一的标识符, // 客户端在发送数据时 globalCallback.set("sn",resultFunc), 通过globalCallback存了一个key为"sn"的回调函数, // 然后通信接收的数据中 返回作为标识符的"sn", 用来查找存的回调函数, 然后处理数据. (因为处理数据的方法可能有多种, 不唯一, 所以用回调函数) const callback = globalCallback.get(ret.sn) callback(ret); 三. js封装代码 import { getToken} from '@/utils/auth' var websock = null; let rec; //断线重连后,延迟5秒重新创建WebSocket连接 rec用来存储延迟请求的代码 let isConnect = false; //连接标识 避免重复连接 let checkMsg = "heartbeat"; //心跳发送/返回的信息 服务器和客户端收到的信息内容如果如下 就识别为心跳信息 不要做业务处理 var globalCallback = new Map(); let createWebSocket = () => { try { initWebSocket(); //初始化websocket连接 } catch (e) { console.log("尝试创建连接失败"); reConnect(); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接 } }; //定义重连函数 let reConnect = () => { console.log("尝试重新连接"); if (isConnect) return; //如果已经连上就不在重连了 rec && clearTimeout(rec); rec = setTimeout(function () { // 延迟5秒重连 避免过多次过频繁请求重连 createWebSocket(); }, 5000); }; //设置关闭连接 let closeWebSocket = () => { websock.close(); }; //心跳设置 var heartCheck = { timeout: 20000, //每段时间发送一次心跳包 这里设置为20s timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象) start: function () { this.timeoutObj = setInterval(function () { console.log("hearting ....") if (isConnect) websock.send(checkMsg); }, this.timeout); }, reset: function () { clearInterval(this.timeoutObj) this.start(); }, stop: function (){ clearInterval(this.timeoutObj) } }; // 初始化websocket function initWebSocket() { // ws地址 // const wsUri = "ws://10.27.100.151:5000/occpws/customWebSocket"; const wsUri = "wss://cloudiot.notioni.com/ws/occpws/customWebSocket"; websock = new WebSocket(wsUri,getToken()) websock.onmessage = function (e) { websocketonmessage(e) } websock.onclose = function (e) { websocketclose(e) } websock.onopen = function () { websocketOpen() heartCheck.start(); } // 连接发生错误的回调方法 websock.onerror = function () { console.log('WebSocket连接发生错误') isConnect = false; //连接断开修改标识 reConnect(); //连接错误 需要重连 } } // 实际调用的方法 function sendSock(agentData, callback, key) { if (!websock){ initWebSocket() } globalCallback.set(key,callback) if (websock.readyState === websock.OPEN) { // 若是ws开启状态 websocketsend(agentData) } else if (websock.readyState === websock.CONNECTING) { // 若是 正在开启状态,则等待1s后重新调用 setTimeout(function () { sendSock(agentData, callback,key) }, 2000) } else { // 若未开启 ,则等待1s后重新调用 setTimeout(function () { sendSock(agentData, callback,key) }, 2000) } } function getSock(key,callback) { globalCallback.set(key,callback) } // 数据接收 function websocketonmessage(e) { let ret = JSON.parse(decodeUnicode(e.data)) if (!ret) { heartCheck.reset() } else { if (ret.msg === "websocket connect success") { } else { if (ret.method === "webSocket_device_transport"){ const callback = globalCallback.get(ret.sn) if (callback && typeof callback === "function") callback(ret); }else if(ret.method === "webSocket_device_alarm"){ const callback = globalCallback.get('deviceAlert') if (callback && typeof callback === "function") callback(ret); } } } // globalCallback(JSON.parse(e.data)) function decodeUnicode(str) { str = str.replace(/\\/g, "%"); //转换中文 str = unescape(str); //将其他受影响的转换回原来 str = str.replace(/%/g, "\\"); //对网址的链接进行处理 str = str.replace(/\\/g, ""); return str; } } // 数据发送 function websocketsend(agentData) { console.log("数据发送",JSON.stringify(agentData)) websock.send(JSON.stringify(agentData)) } // 关闭 function websocketclose(e) { console.log(e) isConnect = false ; //断开后修改标识 heartCheck.stop() console.log('connection closed (' + e.code + ')') } // 创建 websocket 连接 function websocketOpen(e) { isConnect = true console.log('连接成功') } //登录成功后再建立连接 //initWebSocket() // 将方法暴露出去 export { sendSock, getSock, createWebSocket, closeWebSocket, initWebSocket } ———————————————— 版权声明:本文为CSDN博主「Hello 阿凡达」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_38746300/article/details/128675243 |
|
来自: hncdman > 《websocket》