在我 "reset" 之后 setTimeout 是否有触发两次的风险?

Is there a risk that setTimeout will fire twice after I "reset" it?

有时我会使用以下概念:

class ResetableTimeout extends EventEmitter {
  constructor() {
    this.id = -1;
  }
  start(delay) {
    clearTimeout(this.id);
    this.id = setTimeout(() =>{this.emit("done");}, delay);
  }
}

例如,这样的架构可用于节流操作。

现在我注意到在这些情况下这可能会触发两次:

  1. setTimeout 开始超时
  2. start(delay) 被调用并正在执行
  3. 超时触发,回调被推送到事件循环中,等待 start(delay) 结束
  4. clearTimeout 被调用,但超时已经完成
  5. start(delay) 结束并执行超时回调
  6. delay 毫秒后,timeout 的回调再次执行

这可能吗?如果可能如何预防?如果不可能,是什么阻止了它的发生?

不,这是不可能的。如果内部超时已经触发,clearTimeout 将从事件队列中删除超时。它确保在您调用 clearTimeout.

后回调不会 运行

In the spec,有一个活动计时器列表,定时事件循环任务从中获取要执行的回调,并且clearTimeout清除该列表中的计时器,因此即使已经安排了任务,它仍会在执行回调之前检查计时器是否仍处于活动状态。