WebSocket连接必须使用ws://或wss://协议,浏览器禁止用http://或https://创建实例,否则立即抛SecurityError错误。
WebSocket连接必须用ws://或wss://协议,不能用http://
浏览器里直接写 new websocket('http://localhost:8080') 会立刻报错 securityerror: the url's scheme must be 'ws' or 'wss'。这是硬性限制,不是配置问题。
常见错误是本地开发时照抄HTTP服务地址,比如后端跑在 http://localhost:3000,就误以为WebSocket也该连这个地址。实际必须单独起一个WebSocket服务端(如 ws 库监听的 8080 端口),前端连 ws://localhost:8080。
- 开发环境建议前后端端口分离:HTTP服务(如登录页)用
3000,WebSocket服务用8080 - 上线后若共用域名,可复用443端口,但协议必须切为
wss://yourdomain.com,且需配SSL证书 - Chrome 控制台 Network 标签页里看不到
ws://连接,要切到WS子标签才能查状态和消息
服务端广播消息前必须检查 client.readyState === WebSocket.OPEN
Node.js 用 ws 库时,server.clients 是一个 Set,里面可能混着已断开但还没被清理的 socket。直接遍历并调用 client.send() 会抛出 WebSocket is not open 错误,导致整个广播逻辑中断。
正确做法是每次发送前加判断:
server.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
- 不要依赖
client.on('close', ...)回调来同步清理 clients 集合——它可能延迟触发,或因网络异常根本没触发 - 如果需要精确在线人数,应在
connection和close事件里手动维护计数器,而不是靠server.clients.size实时读取 - 生产环境建议加 try/catch 包裹
client.send(),避免单个失败影响其他客户端
前端接收消息必须处理 JSON.parse() 异常
服务端发来的不一定是合法 JSON 字符串。比如调试时手敲 client.send('hello'),前端 event.data 就是原始字符串,JSON.parse(event.data) 会直接报 SyntaxError 并中断后续逻辑。
真实聊天室消息格式通常包含 type、sender、text 等字段,但不能假设所有 incoming data 都符合预期:
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
if (data.type === 'chat') {
appendMessage(`${data.sender}: ${data.text}`);
}
} catch (e) {
console.warn('Invalid message received:', event.data);
}
};
- 服务端应统一用
JSON.stringify()发送结构化数据,但前端永远要防御性解析 - 别把
event.data当作可信输入——XSS 风险存在,尤其当消息内容未做 HTML 转义就直接innerHTML = ... - 如果服务端可能发二进制数据(如文件片段),需先判断
event.data instanceof Blob或ArrayBuffer
自动重连不能只靠 onclose,得自己实现退避策略
ws.onclose 只告诉你断开了,但不会自动重试。用户切后台、休眠、WiFi 切移动网络等场景下,连接极易静默断开,而 onclose 有时根本不触发。
简单轮询重连容易打爆服务端,必须加指数退避:
let reconnectDelay = 1000;
function connect() {
ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => { reconnectDelay = 1000; };
ws.onclose = () => {
setTimeout(connect, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, 30000); // 最大30秒
};
}
- 别在
onerror里重连——它可能由临时网络抖动触发,不一定代表连接已断 - 重连前检查
navigator.onLine,离线时不盲目重试 - 用户主动关闭页面(
beforeunload)时应调用ws.close(),避免服务端残留无效连接
前端消息发送后清空输入框、滚动到底部这些细节容易被忽略,但真正影响体验。WebSocket 不是“连上了就完事”,每个环节都得考虑异常路径——毕竟真实网络从不按教程走。


















