You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();命令?如果服务器无法识别这个指令,可能会主动断开连接。
  • 服务器是否设置了心跳机制?如果客户端没有发送心跳,服务器可能会超时断开。

其他代码优化建议

  1. 替换过时的keyCode:keyCode已经被废弃,建议改用e.key来检测按键,比如e.key === 's'替代e.keyCode == 83,兼容性更好。
  2. 修复组合键逻辑:当前的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;");
    }
  }
}
  1. 优化页面卸载逻辑:onbeforeunload里的socket.send可能无法成功发送(页面卸载时连接可能已关闭),建议用socket.close传递断开原因,让服务器处理用户断开事件:
window.onbeforeunload = function() {
  // 用WebSocket的close方法传递断开信息,服务器监听close事件即可
  socket.close(1000, `${username} has disconnected`);
}

内容的提问来源于stack exchange,提问作者user13129599

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:27:38