捕获 websocket 异步错误需同时监听 onerror 事件以获取底层连接异常,并在发送数据时通过 websocket.send() 的同步抛出机制处理即时失败。由于 websocket 协议本身不提供重传或确认机制,任何网络中断或服务器拒绝都会直接触发错误回调,因此必须在实例化后立即绑定错误处理器,并在业务逻辑中检查 readystate 以确保连接处于开放状态后再执行发送操作。

WebSocket 连接建立阶段的错误如何捕获
在连接建立阶段,错误主要通过 onerror 事件捕获。当 new WebSocket(url) 初始化后,浏览器会尝试进行 TCP 握手和 HTTP 升级。如果 DNS 解析失败、服务器拒绝连接或发生网络超时,onerror 回调会被触发。需要注意的是,onerror 通常不会提供详细的错误信息(如具体的 HTTP 状态码),它仅表示发生了某种错误,此时应结合 onclose 事件来进一步判断连接是否已终止。

const ws = new WebSocket('wss://example.com/socket');
ws.onerror = (event) => {
console.error('WebSocket Error:', event);
// 这里通常无法获取具体错误消息,只能知道出错了
};
ws.onclose = (event) => {
if (!event.wasClean) {
console.warn(`Connection closed due to error: code=${event.code}`);
}
};
ws.onopen = () => {
console.log('Connected successfully');
};
上述代码展示了基本的错误监听结构。当连接失败时,onerror 首先被调用,随后 onclose 也会被触发。开发者应依赖 onclose 中的 event.code 来判断是正常关闭还是异常断开。例如,代码 1006 表示连接异常关闭,而 1000 表示正常关闭。这种组合监听策略确保了无论握手阶段还是后续通信阶段发生的错误都能被捕捉到。
WebSocket 通信过程中的发送错误如何处理
在通信过程中,发送数据时的错误处理主要依赖于 send() 方法的同步行为。虽然 WebSocket 的消息传递是异步的,但 send() 方法本身是同步执行的。如果在调用 send() 时连接尚未打开或已经关闭,该方法会立即抛出 SyntaxError 异常。因此,必须使用 try...catch 块包裹发送逻辑,或者在发送前检查 readyState 属性。

function sendMessage(ws, data) {
try {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
console.log('Message sent successfully');
} else {
console.warn('WebSocket is not open. State:', ws.readyState);
}
} catch (error) {
console.error('Failed to send message:', error);
}
}
// 假设 ws 已经定义并连接
sendMessage(ws, { type: 'ping' });
这段代码演示了安全的发送模式。通过检查 ws.readyState === WebSocket.OPEN,可以避免在连接未就绪时调用 send() 导致的异常。如果连接在发送瞬间断开,send() 可能会抛出异常,此时 catch 块将捕获该错误。此外,即使 send() 成功返回,也不代表消息一定到达服务器,因为 WebSocket 没有应用层确认机制。如果需要可靠性,应在应用层实现 ACK 机制。
基于 readyState 为 CLOSED 时的具体行为问题
当 WebSocket 的 readyState 为 CLOSED(值为 3)时,任何尝试发送数据的操作都会导致 send() 方法抛出 SyntaxError。这是因为在关闭状态下,底层的传输通道已不可用,浏览器强制阻止进一步的写入操作以防止数据丢失或内存泄漏。此时,程序不应继续尝试发送,而应重新建立连接或执行清理逻辑。
if (ws.readyState === WebSocket.CLOSED) {
console.log('Connection is closed. Reconnecting...');
// 触发重连逻辑
reconnect();
} else {
ws.send('data');
}
在实际应用中,检测到 CLOSED 状态后,通常会启动一个指数退避的重连机制。重连时应创建新的 WebSocket 实例,而不是复用旧实例,因为旧实例的状态机已处于终态,无法恢复。同时,应清除旧实例的事件监听器,防止内存泄漏。这种基于状态的显式检查比依赖 try...catch 更清晰,因为它区分了“连接未就绪”和“连接已关闭”两种不同情况,便于实施不同的恢复策略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











