mqtt、websocket的前端生命伴侣

62 阅读2分钟

1. 业务场景

在我们在长连接和轮询的业务场景中,我们经常会遇到这样的问题:

  1. 客户端和服务端之间的连接不稳定,导致可能出现断开。
  2. 服务端的消息可能会延迟到达,导致客户端无法及时获取最新的消息。

为了解决这些问题,我们可以封装一个这样的方法,去监听连接的状态,当连接长时间没有向客户端推送信息时,客户端自动做一些处理。

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(); // 立即生效