MERN Stack集成socket.io时服务端io.on连接回调触发两次如何解决
Socket.IO服务端connection回调触发两次修复方案
根因定位
该问题和React严格模式无关,核心触发原因有两点:
- 客户端socket实例定义在Landing.js的模块顶层,开发环境热重载触发模块重新加载时,会重复创建socket实例,旧实例的连接未手动关闭,导致服务端收到两次连接请求。
- Socket.IO客户端默认开启自动重连逻辑,初始连接时如果出现短暂的跨域握手超时、网络波动,会自动触发重试,也会出现两次连接的现象。
修复步骤
1. 调整客户端socket初始化逻辑
修改Landing.js代码,将socket实例改为组件内部管理,增加连接控制和销毁逻辑:
import React from 'react'; import { io } from 'socket.io-client'; import { CONNECTION_PORT } from '../../config'; class Landing extends React.Component { constructor(props) { super(props); this.state = { products: [], }; // socket实例挂载到组件实例上,避免全局重复创建 this.socket = null; }; componentDidMount() { // 组件挂载时才初始化连接,可自定义重连规则 this.socket = io(CONNECTION_PORT, { autoConnect: true, // 临时关闭重连排查问题,需要重连可开启并配置reconnectionAttempts等参数 reconnection: false }); this.socket.on("connect", () => { console.log('connected') }); this.socket.on('products:auction', (data) => { this.setState({ products: data.message }); }); }; componentWillUnmount() { // 组件卸载时主动断开连接,清除残留连接 if (this.socket) { this.socket.disconnect(); this.socket = null; } } render() { return ( <div> Testing Server Side Error </div> ) }; }; export default Landing;
2. 环境验证
修改后如果开发环境仍出现两次连接,可打包项目部署到生产环境验证,若生产环境仅打印一次连接日志,说明是开发环境热重载特性导致的正常现象,上线后会自动恢复,无需额外处理。
3. 服务端可选加固
如需从服务端彻底避免重复连接影响,可给连接增加唯一标识去重,通过用户id、设备指纹校验同一客户端的连接,存在旧连接时主动将其断开。
内容的提问来源于stack exchange,提问作者jonny.vogel
相关产品推荐
相关产品推荐

