JavaScript中无法直接在宏任务中检测网络断开,但可在宏任务中主动检查连接状态并触发重连逻辑:通过fetch心跳请求验证真实服务可达性,结合setInterval轮询、指数退避重连及online/offline事件辅助响应。

JavaScript 中无法直接在宏任务中“检测网络断开”,因为网络状态变化本身不是宏任务触发源;但可以在宏任务(如 setTimeout、setInterval、fetch 回调、Promise.then 后的微任务清空后的下一个宏任务)中**主动检查连接状态并触发重连逻辑**。核心思路是:用轻量探测(如心跳请求或 navigator.onLine 辅助)+ 定时轮询 + 状态管理,避免阻塞主线程。
用 fetch 心跳请求做可靠探测
navigator.onLine 仅反映浏览器是否认为联网(比如断网后拔网线会延迟响应,Wi-Fi 切换时常为 true 但实际不可用),不可单独依赖。推荐用最小化 HTTP 请求验证真实服务可达性:
- 向后端一个轻量端点(如
/api/health或/ping)发起fetch,设置短超时(如 3–5 秒) - 成功响应(
response.ok === true)说明连接正常;失败(网络错误、超时、非 2xx)则视为断连 - 把该请求放在
setInterval启动的宏任务中,例如每 8–15 秒探测一次,平衡及时性与资源消耗
封装可取消的重连控制器
避免重复启动定时器或并发请求,需管理重连状态:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
let reconnectTimer = null存储当前定时器 ID,每次重连前先clearInterval(reconnectTimer) - 定义
startReconnect():失败后立即尝试一次,再以指数退避(如 1s → 2s → 4s → 8s)调用setTimeout发起下一次探测 - 成功恢复后,清除所有待定重连,并重启常规心跳轮询
结合 online/offline 事件快速响应
虽然 navigator.onLine 不可靠,但系统级的 online 和 offline 事件仍可作为辅助信号:
立即学习“Java免费学习笔记(深入)”;
- 监听
window.addEventListener('offline', () => { /* 触发立即重连尝试 */ }) - 监听
window.addEventListener('online', () => { /* 清除重连状态,恢复心跳 */ }) - 注意:这些事件不保证实时(尤其移动端),必须配合主动探测确认是否真恢复
示例:简洁可运行的重连逻辑
以下代码在宏任务上下文中执行探测与重连(无第三方库):
let isConnected = true;
let reconnectTimer = null;
const PING_URL = '/api/health';
const PING_INTERVAL = 10000; // 常规心跳间隔
const MAX_RETRY_DELAY = 30000;
<p>function pingServer() {
return fetch(PING_URL, { method: 'HEAD', cache: 'no-cache' })
.then(res => {
if (res.ok) return true;
throw new Error(<code>HTTP ${res.status}</code>);
})
.catch(() => false);
}</p><p>function startHeartbeat() {
clearInterval(reconnectTimer);
reconnectTimer = setInterval(async () => {
const ok = await pingServer();
if (!ok && isConnected) {
console.warn('Connection lost, starting reconnect...');
isConnected = false;
triggerReconnect();
} else if (ok && !isConnected) {
console.log('Connection restored');
isConnected = true;
startHeartbeat(); // 恢复常规心跳
}
}, PING_INTERVAL);
}</p><p>function triggerReconnect() {
let retryDelay = 1000;
const attempt = async () => {
const ok = await pingServer();
if (ok) {
isConnected = true;
console.log('Reconnected successfully');
startHeartbeat();
return;
}
if (retryDelay < MAX_RETRY_DELAY) {
setTimeout(attempt, retryDelay);
retryDelay *= 2;
} else {
console.error('Max reconnection attempts reached');
}
};
attempt();
}</p><p>// 初始化
startHeartbeat();</p><p>// 可选:监听系统事件加速响应
window.addEventListener('offline', () => {
if (isConnected) {
isConnected = false;
triggerReconnect();
}
});
window.addEventListener('online', () => {
if (!isConnected) triggerReconnect();
});

















