在 javascript 异步错误处理中,async 函数捕获通知类错误(如 websocket、eventsource 或自定义事件总线发出的信号)的标准做法是结合 try...catch 块与事件监听器。具体而言,应在 async 函数内部注册一个一次性事件监听器,当收到特定错误信号时,通过抛出异常或调用 reject 来中断当前执行流,从而被外层的 await 或 .catch() 捕获。这样做可以将非标准的异步通知转化为标准的 promise 错误链,确保错误能被统一处理。

WebSocket 连接中的实时错误捕获
对于 WebSocket 这种基于事件的异步通信,无法直接使用 await 等待消息,必须通过事件监听将“通知”转换为 Promise 状态。核心做法是在发送请求后,同时启动一个等待响应的 Promise 和一个等待错误的 Promise,利用 Promise.race 竞争机制,一旦收到错误通知立即终止等待并抛出异常。

const ws = new WebSocket('wss://example.com');
function sendMessageWithErrorHandling(message) {
return new Promise((resolve, reject) => {
// 设置超时和错误处理的辅助函数
const timeoutId = setTimeout(() => {
reject(new Error('Request timed out'));
ws.close();
}, 5000);
ws.onmessage = (event) => {
clearTimeout(timeoutId);
resolve(JSON.parse(event.data));
};
ws.onerror = (error) => {
clearTimeout(timeoutId);
reject(new Error('WebSocket error occurred'));
};
ws.send(JSON.stringify(message));
});
}
async function main() {
try {
const result = await sendMessageWithErrorHandling({ action: 'ping' });
console.log('Success:', result);
} catch (error) {
console.error('Caught notification error:', error.message);
}
}
EventSource (SSE) 流式错误处理
Server-Sent Events (SSE) 同样属于持续的通知流,其错误处理需要区分网络断开和服务器推送的业务错误。在 async 函数中,应遍历 onmessage 事件,检查消息类型。若收到特定的错误类型通知,则主动抛出错误以中断当前的异步循环或数据处理流程,防止后续无效数据被处理。

const eventSource = new EventSource('/api/stream');
async function processStream() {
return new Promise((resolve, reject) => {
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'error') {
// 捕获到业务层面的通知错误
reject(new Error(`Stream error: ${data.message}`));
eventSource.close();
return;
}
// 处理正常数据...
console.log('Processing:', data.payload);
};
eventSource.onerror = () => {
reject(new Error('Connection lost'));
eventSource.close();
};
});
}
(async () => {
try {
await processStream();
} catch (e) {
console.error('Failed to process stream:', e);
}
})();
如何处理并发多个通知源的冲突
当 async 函数需要同时监听多个通知源(如多个 WebSocket 或多个 SSE 通道)时,冲突处理的关键在于确定优先级和隔离机制。如果某个通知源发出错误,不应影响其他源的正常运行,但需确保主函数的错误捕获能准确识别是哪个源导致的失败。最佳实践是为每个源创建独立的 Promise 包装器,并使用 Promise.allSettled 或分别进行 try...catch 包裹,避免一个源的错误导致整个上下文崩溃。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











