【问题标题】:Where are running setTimeout stored? [duplicate]运行 setTimeout 存储在哪里? [复制]
【发布时间】:2021-09-08 15:26:41
【问题描述】:

所以我知道setTimeout 在指定的毫秒数后将传递的回调函数存储在任务队列中。我的问题是那些滴答计时器存储在哪里?例如:

setTimeout(func, 1000);

大约 1 秒后,func 被移动到任务队列,然后 - 在 JS 堆栈中。但是setTimeout 调用和将func 移动到任务队列之间的持续时间呢? func 在这一秒期间存储在哪里?

如果我写错了,请纠正我。谢谢!

【问题讨论】:

  • 在javascript引擎中:p
  • Web API 在浏览器的情况下,我猜。
  • 说实话,这样的事情对您的代码没有影响,所以,除非您正在编写自己的 javascript 引擎,否则真的有“需要知道”吗?比如......数组的内容存储在哪里......在某个内存的某个地方,但这有关系吗?是否所有的 javascript 引擎都工作相同(否)... 使用 jacascript,有比内部工作方式更好的事情要关心:p(这只是我的意见,没有伤害没有恶意)
  • 您还可以将它们分配给像var t = setTimeout(f, n) 这样的变量,您以后可以像clearTimeout(t) 这样使用它。
  • @Rod911 - 在至少 Firefox 的浏览器中,setTimeout 只返回一个数字 - 所以..这不是“等待超时的超时代码”:p 我认为 OP 想知道在哪里setTimeout “等待”到“触发”?我认为它只是

标签: javascript settimeout callstack event-loop


【解决方案1】:

根据规范,实现WindowOrWorkerGlobalScope mixin 的对象应该存在一个List of Active Timers(换句话说,该列表应该存在于浏览器的window 对象中),但是,似乎它无法访问。关于这个问题还有其他问题(如this)。

无论如何,如果您非常需要跟踪活动计时器(setIntervalsetTimeout 的列表相同),(在内部,setIntervalsetTimeout 的工作方式相同,但带有repeat 标志),您可以尝试代理这些方法。

类似这样的:

(这个例子可以扩展,更多的数据可以存储在activeTimers集合中,比如idhandlerduration,甚至还有一些辅助方法可以一次触发或中止每个定时器或所有定时器. 以下应尊重规范。)

(() => {
  const activeTimers = new Set();
  const _setTimeout = window.setTimeout;
  const _setInterval = window.setInterval;
  const _clearTimeout = window.clearTimeout;
  const _clearInterval = window.clearInterval;
  
  window.setTimeout = (cb, duration) => {
    let id = -1;
    
    const wrapper = (...args) => {
      activeTimers.delete(id);
      cb(...args);
    }
    
    id = _setTimeout(wrapper, duration);
    
    activeTimers.add(id);
    
    return id;
  };
  
  window.setInterval = (cb, duration) => {
    const id = _setInterval(cb, duration);
    activeTimers.add(id);
    return id;
  };
  
  window.clearTimeout = (id) => {
    _clearTimeout(id);
    activeTimers.delete(id);
  };
  
  window.clearInterval = (id) => {
    _clearInterval(id);
    activeTimers.delete(id);
  };
  
  // YOU CAN EXPORT THIS METHOD FROM A MODULE INSTEAD OF ADDING IT TO THE window OBJECT.
  window.getActiveTimers = () => {
    return Array.from(activeTimers.values());
  };
})();

// USAGE:

console.log('INITIAL TIMERS:', getActiveTimers());

// EXAMPLE 1

setTimeout(() => {
  console.log('TIMER 1 FINISHED:', getActiveTimers());
}, 1000);
console.log('TIMER 1 ADDED: ', getActiveTimers().toString());

// EXAMPLE 2

const timer2Id = setTimeout(() => {
  console.log('TIMER 2 FINISHED:', getActiveTimers());
}, 1000);
console.log('TIMER 2 ADDED: ', getActiveTimers().toString());

clearTimeout(timer2Id);
console.log('TIMER 2 REMOVED: ', getActiveTimers().toString());

// EXPECTED OUTPUT ORDER: [] -> 1 -> 1,2 -> 1 -> []

【讨论】:

  • 这并没有解释它的存储位置。规范“活动计时器列表”没有说明实现者应如何跟踪回调函数及其所有闭包。此外,您的代码无法正确重现 setTimeout 和 setInterval。
  • @Kaiido 我猜说它没有很好地指定是答案的一部分。顺便说一句,刚刚修复了代码,我错过了返回语句。
  • 为什么要指定?问题问的是它是如何实现的,而不是它是如何指定的。而且您的代码仍然无法正确评估。 setTimeout("alert('I am horrible, but I work...')", 0)
  • @Kaiido 这只是一个关于如何代理这些方法的教学示例,而不是替代建议。问题实际上是“运行 setTimeout 存储在哪里?”我发布了更具体的可用信息。我无法做出回答,事情就是这样。这里的每个人都在尽最大努力做出贡献,这个平台的最终目标是集体创造知识。应该已经知道了。
  • 是的,我知道,我的目标就是尽可能地获得“最好的”知识。像这样挥手的东西不会产生最好的知识,并指出“以下应该尊重规范”。当它甚至没有重现任何文档将提供的基础知识时,您不认为也值得评论吗?
猜你喜欢
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 2015-11-03
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多