ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

怎样解决setTimeout执行时间不准确的问题?

2026/8/13 4:26:02 拓冰建站 浏览量
怎样解决setTimeout执行时间不准确的问题?

 怎样解决setTimeout执行时间不准确的问题?

1、while循环;可以使用while循环来轮询检测是否达到执行的时间间隔,如果达到则执行回调,

        缺点:JS是单线程执行的,此时强行将线程用于setTimeout回调函数的执行判断,会使页面进入卡死状态,不可取!

        优点:误差为0

2、web worker+while循环;将while循环放到web worker线程中执行,减轻主线程的负担;

       缺点:worker线程内还是会被while循环占用,无法接收到更多信息;多个定时器无法同时执行,需要开启多个worker线程;

        优点:误差小

// worker.js文件:// worker生成器
const createWorker = (fn, options) => {const blob = new Blob(['(' + fn.toString() + ')()']);const url = URL.createObjectURL(blob);if (options) {return new Worker(url, options);}return new Worker(url);
}
// 创建worker 部分
const worker = createWorker(function () {var count = 1 onmessage = function (e) {const date = Date.now();while (true) {// 拿到当前每一刻的时间和wait时间比对,如果到达wait时间,则发出信号const now = Date.now();  if (now - date >= e.data) {// 限制最多执行20次postMessage(count >= 20 ? 0 : 1);count++return;}}}
})let isStart = false;
const speed = 500
// 每隔半毫秒打印1
function cb () {console.log(1);
}function timer () {worker.onmessage = function (e) {cb()isStart = e.data === 1if (isStart) {worker.postMessage(speed);}}worker.postMessage(speed);
}timer()

3、使用系统时间补偿;当每一次定时器执行后, 都会去获取系统时间进行修正;

        优点:主线程不阻塞,也没创建其他worker线程;执行误差小

        综上:此方案最优

    function timer() {var speed = 500counter = 1start = new Date().getTime()var timer = ''function instance() {var ideal = counter * speedreal = new Date().getTime() - startcounter++var diff = real-idealconsole.log(`实际时间real: ${real}, 理想时间ideal: ${ideal}, 差值diff: ${diff}`);if(counter === 20) {clearInterval(timer)return}// 通过系统时间进行修复,每次wait的时间是动态变化的,这个wait时间通过计算得到timre = window.setTimeout(function(){instance()}, speed - diff)}window.setTimeout(function() {instance()}, speed)}timer()

参考博客:如何实现准时的 setTimeout?

 使用 Web Workers - Web API 接口参考 | MDN