Socket.IO客户端roomName无法传递至服务端的回调问题求助
问题原因
你现在的代码有3个核心错误,导致create事件始终不触发:
connection是服务端独有的监听事件,客户端侧永远不会收到这个事件,你写在客户端的socket.on('connection', ...)整个逻辑块从始至终都不会运行socket.join()是仅服务端可用的API,客户端不存在这个方法,加入房间的操作只能在服务端执行,客户端只需要负责把房间名通过自定义事件传给服务端即可- 客户端代码里没有定义全局可访问的
roomName变量,表单提交时打印这个变量本身就会报未定义错误,你需要先从URL中解析出房间名存为全局变量。
正确实现代码
客户端脚本
首先从URL解析房间名,等Socket连接成功后,主动向服务端发送create事件携带房间名参数,修正后代码如下:
// 从URL解析roomName,示例为query参数取法:URL为xxx.com/chat?room=game1时取到game1,如果你用路径传参可自行修改解析逻辑 const urlParams = new URLSearchParams(window.location.search); const roomName = urlParams.get('room') || 'defaultRoom'; const socket = io(); const messages = document.getElementById('messages'); const form = document.getElementById('form'); const roomContainer = document.getElementById('room-container'); const input = document.getElementById('input'); // 客户端监听连接成功事件用connect,不要和服务端的connection事件名搞混 socket.on('connect', () => { // 主动触发服务端的create监听,把解析到的roomName传过去 socket.emit('create', roomName); console.log("已向服务端提交房间加入申请,房间名:", roomName) }); form.addEventListener('submit', function (e) { console.log(roomName," 表单提交时获取的房间名"); e.preventDefault(); if (input.value) { const alias = socket.id.slice(-5); // 发聊天消息时携带房间信息,方便服务端定向转发 socket.emit('chat message', { room: roomName, content: alias + ": " + input.value }); input.value = ''; } }); socket.on('chat message', function (msg) { const item = document.createElement('ul'); item.textContent = msg; messages.appendChild(item); window.scrollTo(0, document.body.scrollHeight); });
服务端代码
服务端收到create事件后拿到房间名执行加入操作,后续聊天消息定向转发到对应房间,不要用全局io.emit(会发给所有连接的用户),修正后代码如下:
io.sockets.on('connection', (socket) => { socket.on('create', (roomName) => { // join是服务端专属API,可正常执行加入房间操作 socket.join(roomName); console.log("roomName function test,当前加入房间:", roomName); }); socket.on('chat message', (payload) => { // 仅向对应房间广播消息,实现房间隔离 io.to(payload.room).emit('chat message', payload.content); console.log("message to terminal from chat message,所属房间:", payload.room); }); });
效果验证
部署修正后的代码可达到预期效果:
- 客户端连接成功后会自动触发服务端的create事件监听,服务端控制台会正常打印
roomName function test日志 - 同一个房间的用户可以互相收到消息,不同房间的消息完全隔离
- 表单提交时客户端控制台可以正常打印出解析到的roomName值,不会出现未定义报错
注意:不要混淆客户端和服务端的API与事件名,
connection事件、socket.join()方法都只能在服务端环境使用,客户端监听连接成功的事件名是connect,写错运行环境会导致逻辑完全不执行。
内容的提问来源于stack exchange,提问作者econobro
相关产品推荐
相关产品推荐

