websocket初级应用,vue3+node多设备信息同步/事件推送

今天和朋友一起吃饭,偶然发现美团的点餐系统竟然是多设备同步的,因为之前都是谁付款就用谁的手机点餐,饶有兴致,正好借此写个demo,希望对于初次接触websocket的同学来说有个帮助,对于事件推送其实有很多方法
1.轮询:优点是一种通用的实现方式,简单粗暴的向服务端发起请求,几乎所有浏览器都支持。缺点就是服务器压力会比较大,如果是高频交互,也存在一定的延时,取决于轮询时间的逻辑

在这里插入图片描述
例如网易云的扫码登录,每隔几十毫秒发送登录请求检测是否成功扫码

2.Server-Sent Events (SSE):个人比较喜欢的事件推送机制,因为很多场景下不需要与服务器进行交互,只需要从服务器接收数据就可以,例如消息提示,评论点赞提示等等,例如消息列表小红点,但是并不是进行双向通信,所以缺点也很明显。

在这里插入图片描述

3.websocket:双向通信,服务器可以主动推送消息到客户端,客户端也可以主动向服务端推送消息,基本是实时推送,但是ie并不支持,长时间连接对服务器压力较大
首先是web端的实现,采用vue3

首先定义响应式数据,这个一般从后端获取,由于是demo所以我选择写死数据

  const list = ref([
    { title: 'title1', price: 10 },
    { title: 'title2', price: 15 },
    { title: 'title3', price: 20 },
    { title: 'title4', price: 25 },
    { title: 'title5', price: 30 },
    { title: 'title6', price: 35 }
  ]);

然后定义选择每个商品的数量数量

const nums = ref([]);
//   返回几个数据动态添加每项商品的数量控制
  list.value.forEach(() => {
    nums.value.push(0);
  });
  

定义自增自减函数以及计算总价函数

const jia = (index) => {
    nums.value[index]++;
    calculateTotalPrice();//每次自增或自减以后计算总价
  };
  
const jian = (index) => {
    if (nums.value[index] > 0) {
      nums.value[index]--;
      calculateTotalPrice();
    }
  };
  const calculateTotalPrice = () => {
    let total = 0;
    for (let i = 0; i < nums.value.length; i++) {
      total += nums.value[i] * list.value[i].price;
    }
    totalPrice.value = total;
  };
接下来完成后端的操作

1.首先安装websocket

npm install ws

2.太长了不想写,直接贴代码

const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
// 存储每个房间的客户端
let clients = {};
// 存储每个房间的购物车状态
let cartStates = {}; 

server.on('connection', (ws, req) => {
  const urlParams = new URLSearchParams(req.url.split('?')[1]);
  const roomId = urlParams.get('roomId');

  if (!clients[roomId]) {
    clients[roomId] = [];
    cartStates[roomId] = Array(6).fill(0); // 初始购物车状态
  }

  clients[roomId].push(ws);
  ws.send(JSON.stringify({ room: roomId, nums: cartStates[roomId] }));

  ws.on('message', (message) => {
    const { room, nums } = JSON.parse(message.toString('utf8'));
    if (room === roomId) {
      cartStates[room] = nums;

      // 广播更新后的购物车状态给该房间的所有客户端
      clients[room].forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
          client.send(JSON.stringify({ room, nums }));
        }
      });
    }
  });

  ws.on('close', () => {
    clients[roomId] = clients[roomId].filter(client => client !== ws);
    if (clients[roomId].length === 0) {
      delete clients[roomId];
      delete cartStates[roomId];
    }
  });
});

console.log('启动成功端口8080');

3.接下来是客户端全部代码(确保连接到服务端)

<template>
      <div class="container">
        <ul>
          <li v-for="(item, index) in list" :key="index">
            <div class="title">{{ item.title }} - Price: {{ item.price }} </div>
            <div class="btn">
              <button @click="jian(index)">-</button>
              <span>{{ nums[index] }}</span>
              <button @click="jia(index)">+</button>
            </div>
          </li>
          </ul>
        <div class="price">Total Price: {{ totalPrice }}</div>
      </div>
  </template>
  
  <script setup>
  import { ref, onMounted } from 'vue';

  // 定义房间ID,可以根据实际情况设置
  const roomId = 'room1'; 
  const nums = ref([]);
  const list = ref([
    { title: 'title1', price: 10 },
    { title: 'title2', price: 15 },
    { title: 'title3', price: 20 },
    { title: 'title4', price: 25 },
    { title: 'title5', price: 30 },
    { title: 'title6', price: 35 }
  ]);
//   返回几个数据动态添加每项商品的数量
  list.value.forEach(() => {
    nums.value.push(0);
  });
  
  const totalPrice = ref(0);
  const ws = new WebSocket(`ws://localhost:8080?roomId=${roomId}`);
  
  ws.onmessage = (event) => {
    const { room, nums: updatedNums } = JSON.parse(event.data);
    if (room === roomId) {
      nums.value = updatedNums;
      calculateTotalPrice();
    }
  };
  
  const jia = (index) => {
    nums.value[index]++;
    calculateTotalPrice();
    ws.send(JSON.stringify({ room: roomId, nums: nums.value }));
  };
  
  const jian = (index) => {
    if (nums.value[index] > 0) {
      nums.value[index]--;
      calculateTotalPrice();
      ws.send(JSON.stringify({ room: roomId, nums: nums.value }));
    }
  };
  
  const calculateTotalPrice = () => {
    let total = 0;
    for (let i = 0; i < nums.value.length; i++) {
      total += nums.value[i] * list.value[i].price;
    }
    totalPrice.value = total;
  };
  
  ws.onopen = () => {
    console.log('WebSocket connection established.');
  };
  </script>
  
  <style scoped>
  .container{
    width: 400px;
    height: 700px;
    border: solid 3px #000;
    border-radius: 30px;
  }
  ul{
    margin: 40px auto;
    border: solid 1px #000;
    width: 360px;
    list-style-type: none;
    padding: 0;
  }
  li{
    width: 360px;
    height: 40px;
    background-color: antiquewhite;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .title{
    font-size: 20px;
    font-weight: 600;
  }
  .btn{
    height: 40px;
    width: 110px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  button{
    border-radius: 90px;
    width: 30px;
    height: 30px;
    background-color: #f8d63f;
    border: none;
    font-size: 20px;
  }
  .price{
    font-size: 24px;
    font-weight: 600;
  }
  </style>

效果展示

设备1会同步到设备2
设备2也会同步到设备1
新加入的设备加入房间直接获得最新数据

三级标题因为我写的是demo没有引入数据库的操作,所以前后端代码都加入一一些数据处理的操作,如果不考虑数据库只想简单的学习直接复制是可以的

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue.jsNode.js 可以一起实现消息推送的功能。下面是一种简单的实现方式: 1. 在 Vue.js 中,使用 WebSocket 进行实时通信。可以使用 `vue-native-websocket` 或 `vue-socket.io` 等库来简化开发。 2. 在 Node.js 中,使用 `socket.io` 库来处理 WebSocket 的连接和消息推送。 下面是一个简单的示例代码: 在 Vue.js 中: ```javascript // 安装 vue-native-websocket npm install vue-native-websocket import VueNativeSock from 'vue-native-websocket'; Vue.use(VueNativeSock, 'ws://localhost:3000', { reconnection: true, reconnectionAttempts: 5, reconnectionDelay: 3000, }); new Vue({ // ... }); ``` 在 Node.js 中: ```javascript // 安装 socket.io npm install socket.io const express = require('express'); const http = require('http'); const socketIO = require('socket.io'); const app = express(); const server = http.Server(app); const io = socketIO(server); io.on('connection', (socket) => { console.log('A client connected'); // 接收客户端发送的消息 socket.on('message', (data) => { console.log('Received message:', data); // 广播消息给所有连接的客户端 io.emit('message', data); }); // 客户端断开连接 socket.on('disconnect', () => { console.log('A client disconnected'); }); }); server.listen(3000, () => { console.log('Server listening on port 3000'); }); ``` 以上代码实现了一个简单的消息推送功能。当客户端连接到服务器后,可以发送消息,并且服务器会将消息广播给所有连接的客户端。 需要注意的是,这只是一个简单的示例,实际应用中可能需要添加身份验证、权限控制等功能来保证安全性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值