SvelteKit对接NestJS SocketIO时函数内socket.emit不执行求助
问题原因
你遇到的是SvelteKit SSR(服务端渲染)机制导致的socket实例失效问题:
默认情况下SvelteKit的页面组件代码会在服务端预渲染时执行一次,再到客户端hydration时执行第二次。你当前的写法下,服务端会生成一个没有真实网络连接的无效socket实例,客户端hydration后事件回调引用的socket实例可能存在冲突,才会出现初始化时emit正常、后续函数内emit失效的问题。
解决方案
1. 限制socket仅在客户端环境初始化
引入SvelteKit内置的browser变量判断执行环境,只在客户端生成socket实例,避免服务端生成无效实例:
<script> import io from 'socket.io-client'; import { browser } from '$app/environment'; let socket; if (browser) { // 可以额外指定transports强制走websocket协议,避免长轮询导致的异常 socket = io('http://localhost:5000', { transports: ['websocket'] }); socket.on("connect", () => { console.log('连接成功,id:', socket.id); }); socket.on("messages", (arg) => { console.log('收到消息:', arg); }); socket.emit("messages", "executes at load", (err) => { console.log('初始化emit回调:', err); }); } function onSendMessage() { console.log('执行发送函数'); // 执行emit前先判断实例存在且处于连接状态 if (!socket?.connected) { console.log('socket未连接,无法发送'); return } socket.emit("messages", "test", (err) => { console.log('点击事件emit回调:', err); }); } </script> <button on:click={onSendMessage}> Send Message </button>
2. 额外排查点
如果修改后问题仍存在,按以下步骤排查:
- 在
onSendMessage函数内打印socket.id和socket.connected,对比和连接成功时打印的id是否一致,如果不一致说明socket被重复初始化,需将socket实例放到全局store中管理,保证全客户端生命周期复用同一个实例 - 打开浏览器控制台网络面板的「WebSocket」标签,点击按钮时观察是否有对应的消息帧发出,如果有发出但无返回,检查NestJS网关的
@SubscribeMessage注解事件名是否完全匹配messages,以及服务端是否正确调用了ack回调函数
内容的提问来源于stack exchange,提问作者Midnight
相关产品推荐
相关产品推荐

