记录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()
    },
### 使用 Vue.js 实现 WebSocket 实时通信 #### 安装依赖库 为了简化 WebSocket 的集成,可以使用 `vue-socket.io` 插件来管理 WebSocket 连接。安装该插件可以通过 npm 或 yarn: ```bash npm install vue-socket.io ``` 或者 ```bash yarn add vue-socket.io ``` #### 初始化 WebSocket 连接 在项目的入口文件(通常是 main.js),引入并配置 `VueSocketio` 插件以建立与 WebSocket 服务器的连接。 ```javascript import Vue from 'vue'; import App from './App.vue'; // 导入 vue-socket.io 并初始化 import VueSocketio from 'vue-socket.io'; // 创建 Vue 应用实例之前注册全局插件 Vue.use(VueSocketio, 'http://localhost'); new Vue({ render: h => h(App), }).$mount('#app'); ``` 此操作确保了整个应用程序都可以访问 WebSocket 功能[^1]。 #### 组件内定义 Socket 方法 接下来,在具体的 Vue 组件中定义处理来自服务器的消息的方法以及触发特定事件向服务器发送消息的功能。 ```javascript export default { name: "ChatComponent", sockets:{ connect() { console.log("Connected to the server!"); }, customEvent(data) { console.log('This is coming from the socket server:', data); } }, methods: { sendMessage(messageText) { this.$socket.emit('sendMessage', messageText); } } } ``` 这里展示了如何监听名为 `customEvent` 的自定义事件,并通过调用 `$socket.emit()` 向服务器发出带有参数的数据流。 #### 生命周期钩子中的手动连接 如果希望更灵活地控制何时打开 WebSocket 链接,则可以在组件的生命周期方法里显式创建 WebSocket 对象。 ```javascript mounted() { const endpoint = 'ws://example.com/ws'; // 替换成实际的服务端地址 this.socket = new WebSocket(endpoint); this.socket.onopen = () => { console.log('WebSocket connection established.'); }; this.socket.onmessage = (event) => { console.log(`Message received from server: ${event.data}`); }; }, beforeDestroy() { if(this.socket && this.socket.readyState === WebSocket.OPEN){ this.socket.close(); } } ``` 这种方式允许开发者根据业务逻辑决定什么时候开启或关闭 WebSocket 连接[^2]。 #### 错误处理和断线重连策略 考虑到网络波动可能导致连接丢失的情况,建议加入错误捕获机制及自动尝试重新连接的能力。 ```javascript this.socket.onerror = error => { console.error('WebSocket Error:', error); }; let reconnectAttempts = 0; const maxReconnectAttempts = 5; function tryToReconnect(){ setTimeout(() => { if(reconnectAttempts < maxReconnectAttempts){ console.info(`Attempting to reconnect... (${reconnectAttempts + 1}/${maxReconnectAttempts})`); let tempSocket = new WebSocket(endpoint); tempSocket.onopen = () => { console.log('Successfully reconnected!'); this.socket = tempSocket; }; tempSocket.onerror = tryToReconnect.bind({ ...this }); reconnectAttempts++; }else{ console.warn('Max number of attempts reached. Giving up...'); } }, 3000 * Math.pow(2, reconnectAttempts)); } this.socket.onclose = event => { console.log('Connection closed.', event.code, event.reason); tryToReconnect.call(this); }; ``` 上述代码片段实现了当发生异常时记录日志,并按照指数退避算法等待一段时间后再次尝试连接直到达到最大次数为止[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值