持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
在 JavaScript 中可以使用 setTimeout和setInterval 创建定时器。它们接收相同的参数:要执行的函数和执行前的等待时间。setTimeout 函数创建了一个只执行一次的定时器,而 setInterval 创建了一个周期性运行的定时器。
定时器运行机制
定时器与 UI 线程的交互方式有助于把运行耗时较长的脚本拆分为较短的片段。调用的时候会告诉 JavaScript 引擎先等待一段时间,然后添加一个 JavaScript 任务到 UI 队列。
function say(){
alert("Hello world");
}
setTimeout(greeting, 200);
这段代码将在200毫秒后向 UI 队列插入一个执行 say 函数的 JavaScript 任务。这执行之前所有其他 UI 更新和 JavaScript 任务都会执行。然而第二个参数表示任务何时被加入队列而不是在该时间点立即执行。
btn.onclick = function (){
f1();
setTimeout(function(){
document.getElementById('demo').style.color = 'red';
}, 200);
}
当例子中的按钮被点击,他会调用一个方法并设置一个定时器。改变 demo 元素 字体颜色的代码被包含在定时器中,并设置为在200毫秒后加入队列。这200毫秒从 setTimeout 调用时开始计算,而不是在整个函数运行结束后才开始。因此如果 setTimeout 在时间点 n 上被调用,那么执行定时器代码的 JavaScript 任务会在第 n + 250 的时候加入 UI 队列。
定时器代码只有在创建它的函数执行完成之后才有可能被执行。例如如果前面代码中定时器延时变小,然后创建定时器后又调用另一个函数,那么定时器代码有可能在onclick事件处理完成之前加入队列:
btn.onclick = function(){
f1();
setTimeout(function(){
document.getElementById('demo').style.color = 'red';
}, 10);
f2();
}
如果 f2 的执行时间超过 10 毫秒那么定时器代码已经在 onclick 处理完成前加入队列。这样做的影响是定时器代码会在 click 事件处理器执行完成后立刻运行。
无论发生何种情况,创建一个定时器会造成 UI 线程暂停,如果它从一个任务切换到下一个任务。因此定时器代码会重置所有相关的浏览器限制,包括长时间运行脚本定时器。此外调用栈也在定时器的代码中重置为 0。这一特性使得定时器长时间运行 JavaScript 代码理想的跨浏览器解决方案。
定时器的精度
JavaScript 定时器延迟通常不太精准,相差大概几毫秒。仅仅因为你指定定时器延迟 200 毫秒,并不意味着任务一定会在调用 setTimeout 之后过200毫秒时精确的加入队列。
在windows系统中定时器分辨率为15毫秒,也就是是一个延迟15毫秒的定时器将根据最后一次系统时间刷新而转换为 0 或 15。所以延迟最小值建议为 25 毫秒以确保至少有15毫秒延迟。