记录webSocket在vue中的使用

服务端

WebSocketServer.js中

const webSocket = require("ws"); //引入ws服务器模块

const ws = new webSocket.Server({ port: 8000 }); //创建服务器,端口为8000
let clients = {};
let clientNum = 0;
ws.on("connection", (client) => {
  //连接客户端
  // console.log('client', client);

  //给客户端编号,也就是参与聊天的用户
  client.name = ++clientNum;
  clients[client.name] = client;

  // 用户的聊天信息
  client.on("message", (msg) => {
    console.log("用户" + client.name + "说:" + msg);
    console.log(17, msg + ''); // 不转字符串就不会转码  ping变成<Buffer 70 69 6e 67>了
    console.log(18, String(msg)); // 不转字符串就不会转码  ping变成<Buffer 70 69 6e 67>了
    //广播数据发送输出 // 聊天室才需要启动广播给所有人  前后端沟通不需要广播
    // broadcast(client, msg);

    if ('ping' === msg + '') {
      client.send("你跟我说ping我跟你说pong");
      // console.log(21, '你跟我说ping我跟你说pong');
    }
    // msg = String(msg).substring(1, 3); // 前端传过来的字符串得到的时候是带了两个引号的,必须去除两个引号才能等于这里定义的字符串  先String()再正则剔除引号
    // console.log(26, String(msg), "在吗", "在吗" === String(msg), msg + '', String("在吗"), "在吗".toString()); // msg是带引号的字符串,“在吗”是不带引号的

    if ("在吗" === String(msg).substring(1, 3)) {
      console.log('我在');
      client.send("我在");
    }
  });
  //报错信息
  client.on("error", (err) => {
    if (err) {
      console.log(err);
    }
  });
  // 下线
  client.on("close", () => {
    delete clients[client.name];
    console.log("用户" + client.name + "下线了~~");
  });
});

//广播方法
function broadcast(client, msg) {
  for (var key in clients) {
    clients[key].send("用户" + client.name + "说:" + msg);
  }
}

启动服务端:node WebSocketServer.js

vue中:

在main.js同级建socket.js文件

var webSocket = null
var globalCallback = null //定义外部接收数据的回调函数
var pingInterval // 定义心跳
var pongInterval
var pingPong = 'ping'
var urlAll

//初始化websocket
function initWebSocket(url) {
  urlAll = url
  if ('WebSocket' in window) {
    webSocket = new WebSocket(url) //创建socket对象
    console.log(webSocket)
  } else {
    alert('该浏览器不支持websocket!')
  }
  clearInterval(pingInterval) // 移除心跳
  clearInterval(pongInterval) // 移除心跳
  // 心跳机制
  pongInterval = setInterval(() => {
    if (pingPong === 'ping') {
      console.log('没有返回pong 重启webSocket')
      initWebSocket(urlAll)
    }
    // 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong),将重启
    console.log('上次心跳正常返回pong了')
    pingPong = 'ping'
  }, 9500)
  pingInterval = setInterval(() => {
    if (webSocket.readyState === 1) {
      // 检查ws为链接状态 才可发送
      pingPong = 'ping'
      webSocket.send('ping') // 客户端发送ping   我发ping  服务端发pong
    }
  }, 5000)
  wsEvent()
}

// 封装一个函数,处理websocket的几个回调函数
function wsEvent() {
  //打开 // 用于连接成功之后的回调函数
  webSocket.onopen = function () {
    webSocketOpen()
  }
  //收信
  webSocket.onmessage = function (e) {
    webSocketOnMessage(e)
  }
  //关闭 // 用于指定连接关闭之后的回调函数
  webSocket.onclose = function () {
    // initWebSocket() //关闭重连
    webSocketClose()
    clearInterval(pingInterval) // 移除心跳
    clearInterval(pongInterval) // 移除心跳
  }
  //连接发生错误的回调方法
  webSocket.onerror = function () {
    console.log('WebSocket连接发生错误')
    // initWebSocket() //重连
  }
}

//连接socket建立时触发
function webSocketOpen() {
  // if (e === 'LOGIN') {
  const data = {
    type: 'CONNECT',
    token: sessionStorage.getItem('token') || ''
  }
  sendSock(data, function () {})
  // }
  console.log('WebSocket连接成功')
}

//客户端接收服务端数据时触发,e为接受的数据对象
function webSocketOnMessage(e) {
  console.log('接收到信息:', e.data)
  if (e.data === '你跟我说ping我跟你说pong') {
    // 心跳正常
    console.log('心跳正常')
    pingPong = 'pong'
  }
  // const data = JSON.parse(e.data) //根据自己的需要对接收到的数据进行格式化
  const data = e.data //根据自己的需要对接收到的数据进行格式化
  // console.log('globalCallback---data', data)
  globalCallback(data) //将data传给在外定义的接收数据的函数,至关重要。
  /*在此函数中还可以继续根据项目需求来写其他东西。 比如我的项目里需要根据接收的数据来判断用户登录是否失效了,此时需要关闭此连接,跳转到登录页去。*/
}

//发送数据
function webSocketSend(data) {
  webSocket.send(JSON.stringify(data)) //在这里根据自己的需要转换数据格式
}

//关闭socket
function webSocketClose() {
  //因为我建立了多个socket,所以我需要知道我关闭的是哪一个socket,就做了一些判断。
  if (webSocket.readyState === 1 && webSocket.url === urlAll) {
    webSocket.close() //这句话是关键,之前我忘了写,一直没有真正的关闭socket
    console.log('对话连接已关闭')
  }
}

//在其他需要socket地方调用的函数,用来发送数据及接受数据
function sendSock(agentData, callback) {
  // console.log(106, callback)
  globalCallback = callback //此callback为在其他地方调用时定义的接收socket数据的函数,此关重要。
  //下面的判断主要是考虑到socket连接可能中断或者其他的因素,可以重新发送此条消息。
  switch (webSocket.readyState) {
    //CONNECTING:值为0,表示正在连接。
    case webSocket.CONNECTING:
      setTimeout(function () {
        webSocketSend(agentData, callback)
      }, 1000)
      break
    //OPEN:值为1,表示连接成功,可以通信了。
    case webSocket.OPEN:
      webSocketSend(agentData)
      break
    //CLOSING:值为2,表示连接正在关闭。
    case webSocket.CLOSING:
      setTimeout(function () {
        webSocketSend(agentData, callback)
      }, 1000)
      break
    //CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
    case webSocket.CLOSED:
      // do something
      break
    default:
      // this never happens
      break
  }
}

//将初始化socket函数、发送(接收)数据的函数、关闭连接的函数export出去
export default {
  initWebSocket,
  webSocketClose,
  sendSock
}


在main.js中引入它

import socketApi from './socket' //找到封装的socket.js文件
Vue.prototype.socketApi = socketApi //将其挂在原型上,这样 $socketApi就在所有的 Vue 实例中可用了。

在需要使用到webSocket的页面中启用它

data中:

wsUrl: 'ws://localhost:8000', //定义socket连接地址
wsType: 'CONNECT',

mounted() {} 或者created中:

    //建立socket连接
    this.socketApi.initWebSocket(this.wsUrl)
    //data为和后端商量好的数据格式
    const data = {
      type: this.wsType,
      msg: '说的话666'
    }
    this.websocketSend(data) // 这里发送信息给服务端

methods: {}中:

    addplataccount() {
      this.websocketSend('在吗')
    },
    // 接收socket回调函数返回数据的方法
    getConfigResult(res) {
      console.log('getConfigResult接收socket回调函数返回数据', res) //服务端返回的数据
      // this.websocketSend('在吗')  这里res就会收到'我在'
    },
    websocketSend(data) {
      //data为要发送的数据,this.getConfigResult为回调函数,用于在此页面接收socket返回的数据。
      //至关重要!我一开始没写这个,就蒙了,咋才能到拿到回来的数据呢。
      // this.socketApi.sendSock(data, 'sendSock-data')
      this.socketApi.sendSock(data, this.getConfigResult)
    },
    beforeRouteLeave(to, from, next) {
      //在离开此页面的时候主动关闭socket
      this.socketApi.webSocketClose()
      next()
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值