定时器,用来指定某个函数在多少毫秒之后执行。它会返回一个整数,表示定时器的编号,同时你还可以通过该编号来取消这个定时器。
延迟队列:维护了需要延迟执行的任务列表,包括了定时器和 Chromium 内部一些需要延迟执行的任务
ProcessDelayTask函数:专门用来处理延迟执行任务的
直接从 delayed_incoming_queue 延迟队列中,通过 ID 查找到对应的任务,然后再将其从队列中删除掉就可以了。
通过前面setTimeout的实现来看,延迟队列的检查是在当前任务执行完之后进行的,如果当前任务执行过久,势必会影响后续的执行,可以这么认为,setTimeout设置的时间是将延迟任务由延迟任务队列添加到消息队列的时间而不是执行延迟任务的时间
定时器函数里面嵌套调用定时器,也会延长定时器的执行时间,可以先看下面的这段代码:
function cb() { setTimeout(cb, 0); } setTimeout(cb, 0);
在 Chrome 中,定时器被嵌套调用 5 次以上,系统会判断该函数方法被阻塞了,如果定时器的调用时间间隔小于 4 毫秒,那么浏览器会将每次调用的时间间隔设置为 4 毫秒。实现的代码
static const int kMaxTimerNestingLevel = 5; // Chromium uses a minimum timer interval of 4ms. We‘d like to go // lower; however, there are poorly coded websites out there which do // create CPU-spinning loops. Using 4ms prevents the CPU from // spinning too busily and provides a balance between CPU spinning and // the smallest possible interval timer. static constexpr base::TimeDelta kMinimumInterval = base::TimeDelta::FromMilliseconds(4);
如果 setTimeout 设置的延迟值大于 2147483647 毫秒(大约 24.8 天)时就会溢出,那么相当于延时值被设置为 0 了,这导致定时器会被立即执行。
那就是未被激活的页面中定时器最小值大于 1000 毫秒,也就是说,如果标签不是当前的激活标签,那么定时器最小的时间间隔是 1000 毫秒,目的是为了优化后台页面的加载损耗以及降低耗电量。这一点你在使用定时器的时候要注意。
参考
浏览器工作原理与实践
whatwg规范
原文:https://www.cnblogs.com/suihang/p/13445686.html