1. 业务场景
在我们在长连接和轮询的业务场景中,我们经常会遇到这样的问题:
- 客户端和服务端之间的连接不稳定,导致可能出现断开。
- 服务端的消息可能会延迟到达,导致客户端无法及时获取最新的消息。
为了解决这些问题,我们可以封装一个这样的方法,去监听连接的状态,当连接长时间没有向客户端推送信息时,客户端自动做一些处理。
2. 代码实现
class TimeoutWatcher {
constructor() {
this.timeoutTimer = null; // 存储计时器ID
this.lastResetTime = 0; // 最后一次重置时间戳
this.timeout = 10000; // 默认10秒超时
this.onTimeout = () => {}; // 超时回调函数(需外部设置)
}
// 重置计时器(外部调用)
resetTimeout() {
if (this.timeoutTimer) clearTimeout(this.timeoutTimer);
this.lastResetTime = Date.now();
this.timeoutTimer = setTimeout(() => this.handleTimeout(), this.timeout);
}
// 处理超时(私有方法)
handleTimeout() {
const elapsed = Math.floor((Date.now() - this.lastResetTime) / 1000);
console.warn(`[Timeout] ${elapsed}秒未重置,触发超时逻辑`);
this.onTimeout(); // 执行外部传入的回调
// 设置下一次超时检查(10秒后再次触发)
this.timeoutTimer = setTimeout(() => this.handleTimeout(), this.timeout);
}
// 销毁计时器(防止内存泄漏)
destroy() {
if (this.timeoutTimer) clearTimeout(this.timeoutTimer);
}
}
3. 使用示例
// 1. 初始化计时器
const watcher = new TimeoutWatcher();
// 2. 设置超时回调(你的业务逻辑)
watcher.onTimeout = () => {
console.log("执行超时处理...");
// 例如:重连、告警、恢复状态等
};
// 3. 启动计时器
watcher.resetTimeout();
// 4. 你的业务逻辑
// 假设这个函数会被定时的触发,每次服务端推送消息过来都会触发这个函数
fn(){
// ... 你的业务逻辑
watcher.resetTimeout(); //成功接收到服务端信息时重置定时函数
// 如果长时间没有接收到服务端消息的推送,则会长时间不去重置这个定时函数,从而导致超时
}
// 5. 必要时销毁(如组件卸载时)
// watcher.destroy();
- 如果你需要动态调整超时时间
// 修改超时时间(例如改为15秒)
watcher.timeout = 15000;
watcher.resetTimeout(); // 立即生效