/** * 发起websocket请求函数 * @param {string} url ws连接地址 * @param {Object} agentData 传给后台的参数 * @param {function} successCallback 接收到ws数据,对数据进行处理的回调函数 * @param {function} errCallback ws连接错误的回调函数 */ export function WsConnect(url, agentData, successCallback, errCallback) { this.wsUrl = url; this.wsObj = null; // 是否执行重连 true/不执行 ; false/执行 this.lockReconnect = false; // 重连定时器 this.wsCreateHandler = null; // 连接成功,执行回调函数 this.messageCallback = successCallback; // 连接失败,执行回调函数 this.errorCallback = errCallback; // 发送给后台的数据 this.sendDatas = agentData; // 创建ws函数 this.createWebSoket = () => { if (typeof WebSocket === "undefined") { writeToScreen("您的浏览器不支持WebSocket,无法获取数据"); return false; } try { this.wsObj = new WebSocket(url); initWsEventHandle(); } catch (e) { writeToScreen("连接异常,开始重连"); reconnect(); } }; // 手动关闭websocket (这里手动关闭会执行onclose事件) this.closeWebsocket = () => { if (this.wsObj) { writeToScreen("手动关闭websocket"); this.wsObj.close(); // 关闭websocket // this.wsObj.onclose() // 关闭websocket(如果上面的关闭不生效就加上这一条) // 关闭重连 this.lockReconnect = true; this.wsCreateHandler && clearTimeout(this.wsCreateHandler); // 关闭心跳检查 heartCheck.stop(); } }; const initWsEventHandle = () => { try { // 连接成功 this.wsObj.onopen = (event) => { onWsOpen(event); heartCheck.start(); }; // 监听服务器端返回的信息 this.wsObj.onmessage = (event) => { onWsMessage(event); heartCheck.start(); }; this.wsObj.onclose = (event) => { writeToScreen("onclose执行关闭事件"); onWsClose(event); }; this.wsObj.onerror = (event) => { writeToScreen("onerror执行error事件,开始重连"); onWsError(event); reconnect(); }; } catch (err) { writeToScreen("绑定事件没有成功,开始重连"); reconnect(); } }; const onWsOpen = (event) => { writeToScreen("CONNECT"); // // 客户端与服务器端通信 // wsObj.send('我发送消息给服务端'); // 添加状态判断,当为OPEN时,发送消息 if (this.wsObj.readyState === this.wsObj.OPEN) { // wsObj.OPEN = 1 // 发给后端的数据需要字符串化 this.wsObj.send(JSON.stringify(this.sendDatas)); } if (this.wsObj.readyState === this.wsObj.CLOSED) { // wsObj.CLOSED = 3 writeToScreen("wsObj.readyState=3, ws连接异常,开始重连"); reconnect(); this.errorCallback(event); } }; const onWsMessage = (event) => { const jsonStr = event.data; // writeToScreen("onWsMessage接收到服务器的数据: ", jsonStr); this.messageCallback(jsonStr); }; const onWsClose = (event) => { writeToScreen("DISCONNECT"); // e.code === 1000 表示正常关闭。 无论为何目的而创建, 该链接都已成功完成任务。 // e.code !== 1000 表示非正常关闭。 console.log("onclose event: ", event); if (event && event.code !== 1000) { writeToScreen("非正常关闭"); this.errorCallback(event); // 如果不是手动关闭,这里的重连会执行;如果调用了手动关闭函数,这里重连不会执行 reconnect(); } }; const onWsError = (event) => { writeToScreen("onWsError: ", event.data); this.errorCallback(event); }; const writeToScreen = (massage) => { console.log(massage); }; // 重连函数 const reconnect = () => { if (this.lockReconnect) { return; } writeToScreen("5秒后重连"); this.lockReconnect = true; // 没连接上会一直重连,设置延迟避免请求过多 this.wsCreateHandler && clearTimeout(this.wsCreateHandler); this.wsCreateHandler = setTimeout(() => { writeToScreen("重连..." + this.wsUrl); this.createWebSoket(); this.lockReconnect = false; writeToScreen("重连完成"); }, 5000); }; // 心跳检查(看看websocket是否还在正常连接中,不需要服务端返回,单向的) let _this = this let heartCheck = { timeout: 55000, timeoutObj: null, // 重启 reset() { clearTimeout(this.timeoutObj); this.start(); }, // 停止 stop() { clearTimeout(this.timeoutObj); }, // 开启定时器 start() { this.timeoutObj && clearTimeout(this.timeoutObj); this.timeoutObj = setTimeout(() => { writeToScreen("心跳检查,发送ping到后台"); try { const datas = { ping: true }; _this.wsObj.send(JSON.stringify(datas)); } catch (err) { writeToScreen("发送ping异常"); } }, this.timeout); }, }; // 心跳检查(看看websocket是否还在正常连接中,和服务端通信,双向的) // let heartCheck = { // timeout: 15000, // timeoutObj: null, // serverTimeoutObj: null, // // 重启 // reset() { // clearTimeout(this.timeoutObj); // clearTimeout(this.serverTimeoutObj); // this.start(); // }, // // 停止 // stop() { // clearTimeout(this.timeoutObj); // clearTimeout(this.serverTimeoutObj); // }, // // 开启定时器 // start() { // this.timeoutObj && clearTimeout(this.timeoutObj); // this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj); // // 15s之内如果没有收到后台的消息,则认为是连接断开了,需要重连 // this.timeoutObj = setTimeout(() => { // writeToScreen("心跳检查,发送ping到后台"); // try { // const datas = { ping: true }; // _this.wsObj.send(JSON.stringify(datas)); // } catch (err) { // writeToScreen("发送ping异常"); // } // console.log("内嵌定时器this.serverTimeoutObj: ", this.serverTimeoutObj); // // 内嵌定时器 // this.serverTimeoutObj = setTimeout(() => { // writeToScreen("没有收到后台的数据,重新连接"); // reconnect(); // }, this.timeout); // }, this.timeout); // }, // }; }