前端 Node + WebSocket 通讯,这才是更优解(附完整 Demo)

别再用轮询了,WebSocket 才是正道(踩过坑的人都懂)


一、为什么我一开始会被“实时通讯”折磨?

说个真实经历。

之前做一个实时地图(WebGIS那种),要显示设备位置变化。一开始我用的是轮询接口:每隔 3 秒请求一次。

结果呢?

  • 数据延迟:3 秒起步(用户:你这地图是“回忆版”?)
  • 请求压力大:设备一多,后端直接“喘不过气”
  • 前端还要自己控制节流、防抖……写着写着就开始怀疑人生

后来我换成了 WebSocket。

一句话总结:早用早轻松,晚用多踩坑。


二、WebSocket 到底解决了什么问题?

先说核心:

👉 WebSocket 是一个全双工通信协议

也就是说:

  • 客户端可以主动发
  • 服务端也可以主动推
  • 不用每次都 HTTP 请求

对比一下:

方案 问题
轮询 浪费资源 + 延迟
长轮询 勉强能用,但复杂
WebSocket 真·实时

三、原理讲清楚(不讲你迟早踩坑)

WebSocket 本质流程:

  1. 通过 HTTP 发起请求(握手)
  2. 升级协议(Upgrade: websocket)
  3. 建立长连接
  4. 双方随时通信

重点在这里:

👉 连接一旦建立,就不会断(除非你断)

所以你可以理解为:

HTTP 是“一次性聊天”,WebSocket 是“开了个微信群”


四、Node.js 实现 WebSocket 服务端(超简单)

我们用最常见的库:

👉 ws

1、安装依赖

npm install ws

2、服务端代码(完整可跑)

// server.js
const WebSocket = require('ws');

// 创建 WebSocket 服务
const wss = new WebSocket.Server({ port: 3000 });

console.log('WebSocket 服务已启动 ws://localhost:3000');

wss.on('connection', (ws) => {
  console.log('客户端已连接');

  // 发送欢迎消息
  ws.send(JSON.stringify({
    type: 'welcome',
    message: '连接成功'
  }));

  // 接收消息
  ws.on('message', (message) => {
    console.log('收到消息:', message.toString());

    // 广播给所有客户端
    wss.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message.toString());
      }
    });
  });

  // 断开连接
  ws.on('close', () => {
    console.log('客户端断开连接');
  });
});

五、前端 WebSocket 使用(浏览器原生)

不用任何库,浏览器自带。

1、连接服务

const ws = new WebSocket('ws://localhost:3000');

ws.onopen = () => {
  console.log('连接成功');

  ws.send(JSON.stringify({
    type: 'hello',
    message: '前端来了'
  }));
};

2、接收消息

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('收到服务端消息:', data);
};

3、断开连接

ws.onclose = () => {
  console.log('连接关闭');
};

六、实战:WebGIS 实时点位更新(OpenLayers)

来点实际的,不然容易“看懂了但不会用”。

场景

  • 后端推送设备坐标
  • 前端实时更新地图点位

1、模拟服务端推送数据

setInterval(() => {
  const data = {
    type: 'location',
    lng: 116.39 + Math.random() * 0.01,
    lat: 39.9 + Math.random() * 0.01
  };

  wss.clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify(data));
    }
  });
}, 2000);

2、前端更新地图(OpenLayers)

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.type === 'location') {
    const coord = ol.proj.fromLonLat([data.lng, data.lat]);

    feature.setGeometry(new ol.geom.Point(coord));
  }
};

效果:

👉 地图上的点会“自己动”,不用刷新

这就是 WebSocket 的爽点。


七、我踩过的坑(你可以直接避开)

1、连接断了你都不知道

浏览器不会帮你自动重连!

👉 解决:

function connect() {
  const ws = new WebSocket('ws://localhost:3000');

  ws.onclose = () => {
    console.log('重连中...');
    setTimeout(connect, 2000);
  };
}

connect();

2、心跳机制(非常重要)

有些服务器(或代理)会断掉“空闲连接”。

👉 解决:

setInterval(() => {
  ws.send(JSON.stringify({ type: 'ping' }));
}, 30000);

3、数据格式混乱

刚开始我直接传字符串,后来全乱套。

👉 建议:

统一格式:

{
  "type": "xxx",
  "data": {}
}

4、客户端太多,服务器扛不住

WebSocket 是“长连接”,不是免费的。

👉 建议:

  • 做连接限制
  • 用 Redis 做消息分发
  • 或直接上 Socket.IO + 集群

八、什么时候你该用 WebSocket?

直接给你一个判断标准:

👉 满足以下任意一个,就该用:

  • 实时地图(GIS)
  • 聊天系统
  • 实时监控
  • 股票/行情
  • 在线协同

否则:

👉 别滥用(普通 CRUD 真没必要)


九、总结(说点人话)

  • WebSocket 不是“更高级”,而是更合适
  • 核心价值:服务端主动推送
  • 最大坑点:断线、心跳、扩展性

我当时从轮询切到 WebSocket 的时候,有种感觉:

“原来不是我不会写代码,是我选错了工具…”

最后一句(有点重要):

👉 理解通信模型,比背 API 有用一百倍


如果这篇文章对你有帮助,欢迎点赞 👍 收藏 ⭐ 关注 👀
完结,撒花✿✿ヽ(°▽°)ノ✿

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐