TypeScript使用Socket.io时类属性与变量运行结果不一致求解
问题原因分析
核心差异点
- 第一种写法的
connect事件回调中,访问的是this.chatSocket,也就是Admin实例当前的chatSocket属性值,属性值随时可能被后续操作覆盖 - 第二种写法的
connect事件回调中,访问的是通过参数传入的局部变量test,该变量被闭包捕获,永远指向joinChat调用时传入的那个Socket实例,不会被后续操作修改
触发场景(最常见的情况)
你大概率在第一个Socket实例还没完成连接的时候,重复调用了connectChat方法:
- 第一次调用
connectChat,创建Socket实例A,赋值给this.chatSocket,同时调用joinChat注册connect事件回调 - 实例A还在建立连接的过程中,你第二次调用了
connectChat,创建新的Socket实例B,覆盖了this.chatSocket的赋值 - 之后实例A完成连接,触发connect事件:
- 第一种写法的回调中访问
this.chatSocket,此时已经是还没完成连接的实例B,所以connected属性为false - 第二种写法的回调中访问的是第一次传入的局部变量
test,也就是已经完成连接的实例A,所以connected属性为true
- 第一种写法的回调中访问
其他附带问题
你目前的joinChat方法返回的Promise永远不会触发resolve,会导致Promise.all一直处于pending状态,后续依赖这个Promise的逻辑永远不会执行。
修复方案
- 避免重复调用
connectChat,调用前先判断当前是否已有活跃连接:
connectChat() { // 已有活跃连接直接返回 if (this.chatSocket?.connected) return Promise.resolve() this.initQueryAndAuth(); // 其他原有逻辑 }
- 如果需要保留类属性存储Socket实例的写法,注册事件时先把当前实例存为局部变量,避免被覆盖:
joinChat() { // 保存当前Socket实例的引用,避免后续属性覆盖导致引用错误 const currentSocket = this.chatSocket return new Promise<void>(resolve => { console.log(['From client', "1", currentSocket.connected]); currentSocket.on("connect", () => { console.log(['From client', "4", currentSocket.connected]); resolve() // 连接成功后resolve Promise }); console.log(['From client', "2", currentSocket.connected]); }) }
内容的提问来源于stack exchange,提问作者Rémi Fongaufier
相关产品推荐
相关产品推荐

