令人惊讶的是,我在网络上的任何地方都找不到该问题的答案。
在文档it is stated中,setTimeout和setInterval共享相同的ID池,并且ID 从不重复。如果是这种情况,那么它们最终必须耗尽,因为there is a maximum number计算机可以处理吗?那会发生什么,您不能再使用超时了?
答案 0 :(得分:3)
TL; DR;
这取决于浏览器的引擎。
在Blink和Webkit中:
来自W3C docs:
setTimeout()
方法必须运行以下步骤:
让 handle 是用户代理定义的一个大于零的整数,它将标识此调用要设置的超时。
向 handle 的活动超时列表中添加一个条目。
[...]
也:
每个实现
WindowTimers
接口的对象都有一个活动超时列表和一个活动间隔列表。这些列表中的每个条目均由一个数字标识,该数字在实现WindowTimers
接口的对象的生命周期内,在其列表中必须唯一。
注意:尽管 W3C 提到了两个列表,但WHATWG spec确立了setTimeout
和setInterval
共享一个共同的活动计时器列表。这意味着您可以使用clearInterval()
删除由setTimeout()
创建的计时器,反之亦然。
基本上,每个用户代理都可以按自己的意愿自由实现 handle ID ,唯一的要求是每个对象唯一的整数;您可以获得与浏览器实现一样多的答案。
例如,让我们看看Blink在做什么。
上一个注释:找到眨眼的实际源代码是not such an easy task。它属于Chromium codebase中镜像的GitHub。我将链接GitHub(其当前最新标签:72.0.3598.1
),因为它是导航代码的更好工具。三年前,他们将提交内容推送到 chromium / blink / 。如今, chromium / third_party / WebKit 上正在进行积极的开发,但是正在进行discussion的新迁移。
在Blink(以及显然具有非常相似的代码库的WebKit中)中,维护上述活动计时器列表的责任是属于每个DOMTimerCoordinator
的ExecutionContext
。
// Maintains a set of DOMTimers for a given page or
// worker. DOMTimerCoordinator assigns IDs to timers; these IDs are
// the ones returned to web authors from setTimeout or setInterval. It
// also tracks recursive creation or iterative scheduling of timers,
// which is used as a signal for throttling repetitive timers.
class DOMTimerCoordinator {
DOMTimerCoordinator
将计时器存储在blink::HeapHashMap
集合timers_
的DOMTimerCoordinator::InstallNewTimeout()
集合中,该密钥是(符合规格)TimeoutMap
类型:>
int
回答您的第一个问题(在Blink的地方):每个上下文的活动计时器的最大数量为2 31 -1 ;比您提到的JavaScript using TimeoutMap = HeapHashMap<int, Member<DOMTimer>>;
TimeoutMap timers_;
(2 53 -1)要低得多,但对于正常使用情况而言仍然足够。
对于第二个问题,“ 接下来会发生什么,您不能再使用超时了?”,到目前为止,我只有部分答案。
新计时器由NextID()
创建。它调用私有成员函数DOMTimer::Create
来检索可用的整数键,并调用circular_sequential_id_
来实际创建计时器对象。然后,它将新计时器和相应的键插入MAX_SAFE_INTEGER
中。
timers_
int timeout_id = NextID();
timers_.insert(timeout_id, DOMTimer::Create(context, action, timeout,
single_shot, timeout_id));
以1到2的循环顺序获取下一个id 31 -1:
NextID()
它将seems that nothing的值加1,或者如果超出上限则将其设置为1(尽管int DOMTimerCoordinator::NextID() {
while (true) {
++circular_sequential_id_;
if (circular_sequential_id_ <= 0)
circular_sequential_id_ = 1;
if (!timers_.Contains(circular_sequential_id_))
return circular_sequential_id_;
}
}
+ 1调用UB,但是大多数C实现返回INT_MAX
)。
因此,当INT_MIN
用完ID时,请从1开始重试,直到找到一个空闲的。
但是,如果全部使用它们会发生什么?是什么阻止DOMTimerCoordinator
进入无限循环? contacted Blink developers。 Blink开发人员很可能在假设永远不会同时存在2 31 -1个计时器的情况下对NextID()
进行编码。这说得通;对于NextID()
返回的每个字节,如果DOMTimer::Create()
已满,则需要GB的RAM来存储。如果存储长时间的回调,则总计可能达到TB。更不用说创建它们所需要的时间了。
无论如何,令人惊讶的是,没有实现无尽循环的防护措施,所以我有{{3}},但到目前为止我没有任何回应。如果他们回复,我将更新我的答案。