如何解决Socket.IO断开连接时transport close问题,实现数据库更新
问题解决:Socket.io断开连接时获取用户ID并更新数据库
问题根源
- 服务端
disconnect事件的回调参数并非用户ID,而是连接断开的原因字符串(比如你看到的transport close),直接把这个参数当作用户ID使用必然出错。 - 客户端主动调用
io.emit("disconnect")属于错误操作,Socket.io会在连接自然中断(页面关闭、网络异常等)时自动触发服务端的disconnect事件,无需手动发送。 - 用户连接时没有将用户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
相关产品推荐
相关产品推荐

