You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Node.js/WS:如何在服务端抛出可被客户端处理的错误?

解决WebSocket连接数超限后触发客户端onerror的问题

我来帮你搞定这个问题——你想在WebSocket连接数超过2个时让客户端的onerror方法捕获错误,但直接在服务端抛错根本传不到客户端,对吧?这是因为在ws包的connection事件回调里直接throw错误,只会触发服务端的异常(如果没捕获的话),并不会通过WebSocket协议把错误通知给客户端。下面是具体的实现方案:

核心思路

当新连接进来后,先检查当前总连接数是否超过限制:

  1. 如果超限,先给客户端发送错误提示(可选但友好)
  2. 用带错误码的关闭帧主动断开连接,触发客户端的onerroronclose事件
  3. 及时从服务端的连接集合中移除这个超限连接

服务端代码(server.js)

const WebSocket = require('ws');
const theWebSocketServer = new WebSocket.Server({ port: 8080 });

theWebSocketServer.on('connection', function connection(websocket) {
  // 注意:ws的clients是Set对象,用size获取数量,不是length!
  if (theWebSocketServer.clients.size > 2) {
    // 1. 先给客户端发送错误原因(可选,客户端可通过onmessage接收)
    websocket.send(JSON.stringify({ error: '连接数已达上限,最多允许2个连接' }));
    
    // 2. 发送带自定义错误码的关闭帧
    // 4001属于WebSocket私有错误码范围(4000-4999),适合业务自定义错误
    websocket.close(4001, '连接数超限');
    
    // 3. 手动从连接集合移除当前连接(close后会自动移除,但提前处理更稳妥)
    theWebSocketServer.clients.delete(websocket);
    return;
  }

  // 正常连接的后续处理逻辑
  console.log('新连接建立,当前连接数:', theWebSocketServer.clients.size);
  
  websocket.on('message', (data) => {
    console.log('收到客户端消息:', data.toString());
  });

  websocket.send('连接成功');
});

客户端代码示例

要确保客户端同时监听onerroronclose(不同环境下触发逻辑可能有差异):

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

// 监听错误事件
ws.onerror = (error) => {
  console.error('WebSocket错误捕获:', error);
};

// 监听关闭事件,处理服务端发送的错误码和原因
ws.onclose = (event) => {
  if (event.code !== 1000) { // 1000是正常关闭码
    console.error('连接异常关闭:', event.reason, '错误码:', event.code);
  }
};

// 监听服务端发送的错误消息
ws.onmessage = (event) => {
  try {
    const data = JSON.parse(event.data);
    if (data.error) {
      console.error('服务端返回错误:', data.error);
    } else {
      console.log('服务端消息:', event.data);
    }
  } catch (e) {
    console.log('服务端消息:', event.data);
  }
};

关键注意点

  • 不要直接throw错误:服务端的throw只会在自己的进程里触发异常,不会传递给客户端,必须通过WebSocket协议帧主动通知
  • 使用clients.size而非length:ws包的server.clients是一个ES6 Set对象,获取数量要用size属性,你之前的length写法是错误的,会导致判断不准确
  • 自定义错误码:选择4000-4999范围内的错误码,这是WebSocket协议预留的私有业务错误码区间,避免和标准错误码冲突
  • 客户端双监听:部分浏览器/环境下,服务端主动发送错误关闭帧会触发onerror,但有些只会触发onclose,所以同时监听两个事件更稳妥

内容的提问来源于stack exchange,提问作者Anna Jeanine

火山引擎 最新活动