JavaScript WebSocket无法保持连接:聊天室连接即断开求助
解决WebSocket聊天室连接断开与SyntaxError问题
首先,咱们先搞定那个报错的SyntaxError: Unexpected token ':',这个错误直接导致了脚本逻辑中断,甚至可能间接引发WebSocket连接异常断开。
错误根源:eval的语法问题与字符串未转义
你的代码里用eval(e.data)直接执行服务器发来的内容,但如果服务器返回的JS代码存在语法错误(比如字符串未正确闭合),就会触发这个错误。比如当用户名或消息里包含单引号时(比如用户名是O'Conner),你发送的alert语句就会变成:
alert('Message recieved from O'Conner: Hello!');
这里的单引号直接破坏了字符串结构,eval执行时就会抛出Unexpected token ':'的错误。
修复方案1:替换eval为安全的消息格式(推荐)
直接执行服务器发来的代码非常危险,而且容易出语法问题。建议你和服务器约定用JSON格式传递消息,比如:
客户端发送消息时改成JSON:
function send(message) { if (message !== "Stop") { const msgData = JSON.stringify({ type: "alert", content: `Message recieved from ${username}: ${message}` }); socket.send(msgData); save(`Message sent: ${message}`); } }
服务器返回消息也用JSON格式,客户端onmessage里解析处理:
socket.onmessage = function(e) { try { const msg = JSON.parse(e.data); if (msg.type === "alert") { alert(msg.content); } save(msg.content); } catch (err) { console.error("Failed to process message:", err, "Raw message:", e.data); alert("Error handling message: " + err.message); } };
修复方案2:临时修复字符串转义(不推荐,但快速生效)
如果暂时不想改JSON格式,至少要对用户名和消息里的单引号进行转义,避免破坏alert语句的语法:
// 新增转义函数 function escapeQuotes(str) { return str.replace(/'/g, "\\'"); } // 修改send函数 function send(message) { if (message !== "Stop") { const escapedUsername = escapeQuotes(username); const escapedMessage = escapeQuotes(message); socket.send(`alert('Message recieved from ${escapedUsername}: ${escapedMessage}');`); save(`alert('Message sent: ${escapedMessage}');`); } } // 同样修改onopen里的用户连接提示 socket.onopen = function() { socket.send("otherusers();"); alert("Connected to server. Press 'esc' to disconnect. Type 'send' to send something."); alert("The users on this server will be displayed shortly (if any)"); const escapedUsername = escapeQuotes(username); socket.send(`alert('A new user has connected with the username ${escapedUsername}.')`); }; // 修改onbeforeunload里的断开提示 window.onbeforeunload = function() { const escapedUsername = escapeQuotes(username); socket.send(`alert('${escapedUsername} has disconnected from the server.')`); socket.close(); }
解决连接立即断开的问题
连接建立后马上断开,很大概率是因为onmessage里的未捕获异常导致脚本崩溃,进而触发WebSocket连接异常关闭。咱们需要给eval(或JSON解析)加上异常捕获:
socket.onmessage = function(e) { try { // 这里放原来的eval或者JSON解析逻辑 eval(e.data); save(e.data); } catch (err) { console.error("Error executing message:", err, "Message content:", e.data); alert("Failed to process server message: " + err.message); // 捕获错误后,连接不会因为脚本崩溃而断开 } };
另外,你也需要检查服务器端的WebSocket实现:
- 服务器是否能正确处理你发送的
otherusers();命令?如果服务器无法识别这个指令,可能会主动断开连接。 - 服务器是否设置了心跳机制?如果客户端没有发送心跳,服务器可能会超时断开。
其他代码优化建议
- 替换过时的
keyCode:keyCode已经被废弃,建议改用e.key来检测按键,比如e.key === 's'替代e.keyCode == 83,兼容性更好。 - 修复组合键逻辑:当前的
s-e-n-d组合键检测在keyup时没有重置状态,容易出现逻辑混乱,比如在keyup里对应重置变量:
function keyup(e) { if (e.keyCode === 83) s = false; if (e.keyCode === 69) ee = false; if (e.keyCode === 78) n = false; // 原来的192按键逻辑 if (e.keyCode == 192) { var messages = document.getElementsByClassName("ALINTIOKNALSFJI"); for (var i = 0, max = messages.length; i < max; i++) { messages[i].setAttribute("style", "color: transparent; background-color: transparent;"); } } }
- 优化页面卸载逻辑:
onbeforeunload里的socket.send可能无法成功发送(页面卸载时连接可能已关闭),建议用socket.close传递断开原因,让服务器处理用户断开事件:
window.onbeforeunload = function() { // 用WebSocket的close方法传递断开信息,服务器监听close事件即可 socket.close(1000, `${username} has disconnected`); }
内容的提问来源于stack exchange,提问作者user13129599
相关产品推荐
相关产品推荐

