You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Socket.IO断开连接时transport close问题,实现数据库更新

问题解决:Socket.io断开连接时获取用户ID并更新数据库

问题根源

  1. 服务端disconnect事件的回调参数并非用户ID,而是连接断开的原因字符串(比如你看到的transport close),直接把这个参数当作用户ID使用必然出错。
  2. 客户端主动调用io.emit("disconnect")属于错误操作,Socket.io会在连接自然中断(页面关闭、网络异常等)时自动触发服务端的disconnect事件,无需手动发送。
  3. 用户连接时没有将用户ID与对应的socket实例绑定,导致断开连接时无法获取到正确的用户标识。

修正后的代码

服务端代码

// 处理用户连接事件,绑定用户ID到socket实例
socket.on('user_connected', function(userid) {
  // 将用户ID关联到当前socket对象
  socket.userid = userid;
  users[userid] = socket.id;
  console.log(`用户 ${userid} 已上线`);
  // 通知其他客户端该用户上线
  io.emit("user_connected", userid);
});

// 处理连接断开事件
socket.on('disconnect', function(reason) {
  // 从socket对象中取出之前绑定的用户ID
  const userid = socket.userid;
  if (userid) {
    console.log(`用户 ${userid} 断开连接,原因:${reason}`);
    // 此处执行数据库更新操作,示例:
    // db.execute('UPDATE users SET is_online = 0 WHERE id = ?', [userid]);
    // 通知其他客户端该用户下线
    io.emit("user_disconnect", userid);
    // 从在线用户列表中移除
    delete users[userid];
  }
  console.log('连接已断开');
});

客户端代码

const io = io("http://localhost:5500");
const userid = sessionStorage.getItem('userid');

// 连接成功后发送用户上线事件
io.on('connect', function() {
  if (userid) {
    io.emit("user_connected", userid);
  }
});

// 监听其他用户上线通知
io.on("user_connected", function(userid) {
  console.log(`用户 ${userid} 已上线`);
});

// 监听其他用户下线通知
io.on("user_disconnect", function(userid) {
  console.log(`用户 ${userid} 已下线`);
});

// 无需手动发送disconnect事件,Socket.io会自动处理连接断开逻辑

核心要点

  • 必须在用户成功建立连接后,将用户ID绑定到服务端的socket对象上,这样断开连接时才能通过socket.userid获取到正确的用户标识。
  • 服务端disconnect事件的第一个参数是断开原因,不能当作用户ID使用。
  • 客户端不要手动触发disconnect事件,Socket.io会在连接自然中断时自动触发服务端对应事件。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:57:36