TimeoutManager.ets 5.28 KB
/**
 * 超时控制与管理
 *
 * setTimeout和setInterval函数,都返回一个整数值,表示计数器编号。
 *
 * let timerId = setTimeout(func|code, delay);
 * setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数。
 * setTimeout的第二个参数如果省略,则默认为0。
 *
 * 如:
 * let timerId1 = setTimeout(fun1, 1000);
 *
 * setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
 * let intervalId1 = setInterval(fun2, 1000);
 * 上面代码中,每隔1000毫秒就会执行fun2函数,会无限运行下去,直到关闭当前窗口。
 *
 * 注意:
 * setInterval指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。
 * 比如,setInterval指定每 100ms 执行一次,每次执行需要 5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。
 *
 *
 * setTimeout和setInterval函数,都返回一个整数值,表示计数器编号。将该整数传入clearTimeout和clearInterval函数,就可以取消对应的定时器。
 *
 * clearTimeout(timerId1)
 * clearInterval(intervalId1)
 */
import { WDGroup } from '../layout/WDGroup';
import HashMap from '@ohos.util.HashMap';
import { Lego } from './LegoService';

export namespace Timeout {

  /**
   * 超时管理
   */
  export class TimeoutManager {
    /**
     * 超时时长
     */
    private static TASK_TIMEOUT: number = 5000;
    /**
     * 任务超时回调
     */
    private callback: Callback;
    /**
     * 用于存放所有进行中的任务
     */
    private taskMap: HashMap<WDGroup, Task>;
    /**
     * 超时管理器单例实例
     */
    private static instance: TimeoutManager;

    private intervalId:number = -1;

    /**
     * 构造函数
     *
     * @param group 发出请求的MGGroup实例
     * @param startTime 任务开始时间戳
     * @param timeout 超时限制时常
     */
    constructor(callback: Callback) {
      this.taskMap = new HashMap<WDGroup, Task>();
      this.callback = callback;
      // todo:
      // 如果队列中没有检查消息,TASK_TIMEOUT后检查。
      // if (this.intervalId == -1) {
      //   this.intervalId = setInterval(() => {
      //     this.checkTimeout();
      //   }, TimeoutManager.TASK_TIMEOUT);
      // }
    }

    /**
     * 添加任务,监控超时状态。
     * @param group MGGroup对象
     * @param callback 回调
     */
    public addTask(group: WDGroup, callback: Lego.Callback) {
      let task: Task = this.taskMap.get(group);
      let timestamp: number = new Date().getTime(); // 单位毫秒
      if (task == null) {
        this.taskMap.set(group, new Task(group, callback, timestamp, TimeoutManager.TASK_TIMEOUT));
      } else {
        task.setStartTime(timestamp);
        task.setCallback(callback);
      }
    }

    /**
     * 移除任务,说明任务已经完成,不再监控超时状态。
     * @param group MGGroup对象
     */
    public removeTask(group: WDGroup) {
      this.taskMap.remove(group);
    }

    /**
     * 检查是否有已经超时的任务,如有则回调超时状态。
     */
    private checkTimeout() {
      // TODO: 遍历任务列表检查是否有超时任务
      this.taskMap.forEach((task: Task, group: WDGroup) => {
        if (task == null || task.isTimeout()) {
          // 超时回调
          if (this.callback) {
            this.callback.onTimeout(group, task.callback);
          }
        }
      })
    }
  }

  /**
   * 任务
   */
  class Task {
    /**
     * MGGroup实例
     */
    private group: WDGroup;
    /**
     * 请求回调
     */
    public callback: Lego.Callback;
    /**
     * 任务开始时间戳
     */
    private startTime: number;
    /**
     * 超时限制时常
     */
    private timeout: number;

    /**
     * 构造函数
     *
     * @param group 发出请求的MGGroup实例
     * @param startTime 任务开始时间戳
     * @param timeout 超时限制时常
     */
    constructor(group: WDGroup, callback: Lego.Callback, startTime: number, timeout: number) {
      this.group = group;
      this.callback = callback;
      this.startTime = startTime;
      this.timeout = timeout;
    }

    /**
     * 更新任务开始时间戳
     *
     * @param startTime 任务开始时间戳
     */
    public setStartTime(startTime: number): void {
      this.startTime = startTime;
    }

    public setCallback(callback: Lego.Callback): void {
      this.callback = callback;
    }

    /**
     * 检查任务是否超时
     *
     * @return 是否超时
     */
    public isTimeout(): boolean {
      let timestamp: number = new Date().getTime(); // 单位毫秒
      return timestamp - this.startTime - this.timeout >= 0;
    }
  }

  /**
   * 超时回调
   */
  export interface Callback {
    /**
     * Group请求超时回调
     * @param group MGGroup对象
     * @param callback 回调';
     */
    onTimeout: (group: WDGroup, callback: Lego.Callback) => void;
  }
}