WebSocket

浏览器通过JavaScript向服务器发出建立WebSocket链接的请求,链接建立后,客户端和服务器端就可以通过TCP链接直接交互数据。WebSocket链接后可以通过send()方法来向服务器发送数据,并通过onnessage事件来接受服务器返回的数据。

创建WebSocket对象

let ws = new WebSocket(server);

WebSocket属性

属性

描述

ws.readyState

WebSocket.CONNECTING: 0正在链接

WebSocket.OPEN: 1 链接成功,可以通信

WebSocket.CLOSING: 2 链接正在关闭

WebSocket.CLOSED: 3 链接已经关闭,或者打开链接失败

ws.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

ws.onopen

连接建立时触发

ws.onmessage

客户端接收服务端数据时触发

ws.onerror

通信发生错误时触发

ws.onclose

连接关闭时触发

ws.binaryType

指定有链接所传递的二进制数据类型(可选值:blobarraybuffer)

WebSocket 方法

方法

描述

ws.send()

使用链接发送数据

ws.close()

关闭链接

WebSocket使用

创建WebSocket实例

首先判断当前浏览器是否支持WebSocket,如果支持则创建WebSocket实例,并初始化事件函数。

let ws = null;
const server = `ws://xxx.xx.xxx.xxx:xxxx`;// WebSocket服务地址
let createWebSocket = (server) => {
  try {
    if(window["WebSocket"]){
      ws = new WebSocket(server)
    }else if(window["MozWebSocket"]){
      ws = new MozWebSocket(server)
    } else  {
      Notification({message:"当前浏览器不支持websocket协议,建议使用Chrome浏览器",type:"success"})
    }
    initEventHandle()// 连接建立时触发
  } catch (e) {
    console.log("ERR-----------捕获异常", e)
  }
};

初始化事件函数

onerroronclose进行报错或链接断开后的一下业务逻辑操作(如:重连操作)
onopen:初始化状态(如:心跳检测、重连次数)
onmessage:对服务器发送的消息做处理

let initEventHandle = () => {
  // 连接报错
  ws.onerror = function (evt, e) {
    console.log("连接报错");
  };
  // 连接关闭
  ws.onclose = function (evt) {
    console.log("连接关闭---" + new Date().toLocaleTimeString());
  };
  // 链接成功
  ws.onopen = function (evt) {
    console.log("链接成功");
  };
  // 接受数据
  ws.onmessage = function (evt) {
     console.log("收到消息");
  };
};
重连机制

当浏览器断开WebSocket链接时或链接失败时,会出发oncloseonerror事件。我们可以在oncloseonerror中调用重连方法。为了避免重连方法的过多请求,可以定义一个状态来控制,也可以设置最大重连次数。

let count = 0;// 记录次数
let lockReconnect = false;// 避免ws重复连接
let reconnect = (server) => {
  if (count >= 5) return console.log("超出重连次数!");
  if (lockReconnect) return false;
  lockReconnect = true;
  setTimeout(function () {     // 设置延迟避免请求过多
    console.log("6----------开始重连");
    lockReconnect = false;
    count++;
  }, 5000);
};

vue 更新dependencies vue 更新 websocket问题_vue 更新dependencies

心跳检测

为了保证WebSocket与服务器之间正常通信,可以每隔一段时间通过send()方法向服务器发送一个心跳信息。在onmessage拿到返回的心跳就说明连接正常。(服务器收到信息会返回相应的信息)

const heartCheck = {
  timeout: 25000,        // 设置心跳时间
  timeoutObj: null,
  serverTimeoutObj: null,
  reset: function () {
    clearTimeout(this.timeoutObj);
    clearTimeout(this.serverTimeoutObj);
    return this;
  },
  start: function () {
    const self = this;
    this.timeoutObj = setTimeout(function () {
      // 这里发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
      ws.send("ping----------Ping");
      self.serverTimeoutObj = setTimeout(function () {
        // 如果超过一定时间还没重置,说明后端主动断开了
        // 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
        ws.close();
      },self.timeout)
    },this.timeout)
  }
};

监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。

window.onbeforeunload = function () {
  ws.close();
};

在Vue中使用WebSocket

main.js中引入全局并挂载到Vue原型上。

import socket from "@/utils/webSocket";
Vue.prototype.startWebSocket  = socket.startWebSocket;

完整代码:

// webSocket.js
import {Notification} from "element-ui";
import { getToken } from '@/utils/auth';

let count = 0;// 记录计数
let lockReconnect = false;//避免ws重复连接
const text1 = "您有新的订单,请及时处理!";
let ws = null;// 判断当前浏览器是否支持WebSocket
const server = `ws://xxx.xx.xxx.xxx:xxxx?Admin-Token=${getToken()}`;// WebSocket服务地址
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
  ws.close();
};
// 重连
let reconnect = (server) => {
  if (count >= 5) return console.log("超出重连次数!");
  if (lockReconnect) return false;
  lockReconnect = true;
  setTimeout(function () {     //没连接上会一直重连,设置延迟避免请求过多
    createWebSocket(server);
    lockReconnect = false;
    count++;
  }, 5000);
};
// 创建实例websocket
let createWebSocket = (server) => {
  try {
    if('WebSocket' in window){
      ws = new WebSocket(server)
    }else if('MozWebSocket' in window){
      ws = new MozWebSocket(server)
    } else  {
      Notification({message:"当前浏览器不支持websocket协议,建议使用现代浏览器",type:"success"})
    }
    // 连接建立时触发
    initEventHandle()
  } catch (e) {
    console.log("ERR-----------捕获异常", e)
  }
};
// 初始化事件函数
let initEventHandle = () => {
  // 连接报错
  ws.onerror = function (evt, e) {
    reconnect(server)
  };
  // 连接关闭
  ws.onclose = function (evt) {
    console.log("连接关闭---" + new Date().toLocaleTimeString());
    reconnect(server)
  };
  // 链接成功
  ws.onopen = function (evt) {
    heartCheck.reset().start();// 心跳检测重置
    count = 0;// 重置重连次数
  };
  // 接受数据
  ws.onmessage = function (evt) {// 如果获取到消息,心跳检测重置
    heartCheck.reset().start();// 拿到任何消息都说明当前连接是正常的
    let eventData  = undefined;
    try {
      eventData = JSON.parse(evt.data);
      handMsg(eventData)
    }catch (e) {
      console.log("捕获异常: 当前返回的数据不能解析;");
      console.log("内容:" + evt.data)
    }
  };
};
// 心跳检测
const heartCheck = {
  timeout: 25000,        // 设置心跳时间
  timeoutObj: null,
  serverTimeoutObj: null,
  reset: function () {
    clearTimeout(this.timeoutObj);
    clearTimeout(this.serverTimeoutObj);
    return this;
  },
  start: function () {
    const self = this;
    this.timeoutObj = setTimeout(function () {
      // 这里发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
      ws.send("ping--------------Ping");
      self.serverTimeoutObj = setTimeout(function () {
        // 如果超过一定时间还没重置,说明后端主动断开了
        // 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
        ws.close();
      },self.timeout)
    },this.timeout)
  }
};
// 处理消息
let handMsg = (eventData) => {
  if (ws.readyState === WebSocket.OPEN) {
    if (eventData.code === "2000" && eventData.type === "order_notice") {
      Notification({message: text1,type:"warning"})
    }
  }
};
let startWebSocket = () => {
  createWebSocket(server)
};
export default { startWebSocket }

效果图:

vue 更新dependencies vue 更新 websocket问题_vue_02