JS定时器不准及解决方案

原因:.Eventloop 循环机制中,异步事件 setInterval 到时后会把回调函数放入消息队列中,主线程的任务执行完毕后依次执行消息队列的任务,由于消息队列中存在大量任务,其他任务执行时间就会造成定时器回调函数的延迟,如果不处理则会一直叠加延迟
示例:

var startTime = new Date().getTime();
var count = 0;
//耗时任务
setInterval(function(){
    var i = 0;
    while(i++ < 100000000);
}, 0);


setInterval(function(){
    count++;
    console.log(count + ' --- ' + (new Date().getTime() - (startTime + count * 1000)));
}, 1000);

示例输出:
JS定时器不准及解决方案_第1张图片
解决方案1: 动态计算时差
根据定时器最开始时间计算当前时间(回调函数执行时间)与开始时间的误差,用期望时差减误差作为下一次任务的时间间隔
注:时差过大(超过期望时差)时,由于无法时间回流。。。只能按没有间隔处理,减轻影响

var startTime = new Date().getTime();
var count = 0;
//耗时任务
setInterval(function(){
    var i = 0;
    while(i++ < 100000000);
}, 0);
function handle() {
    count++;
    var offset = new Date().getTime() - (startTime + count * 1000);
    var nextTime = 1000 - offset;
    if (nextTime < 0) nextTime = 0;
    setTimeout(handle, nextTime);
     
    console.log(count + ' --- ' + (new Date().getTime() - (startTime + count * 1000)));
}
setTimeout(handle, 1000);

输出结果:
JS定时器不准及解决方案_第2张图片
解决方案2: 使用 web Worker
将定时函数作为独立线程执行

<script type="text/javascript">
var startTime = new Date().getTime();
var count = 0;
//耗时任务
setInterval(function(){
    var i = 0;
    while(i++ < 100000000);
}, 0);

// worker 解决方案
let worker = new Worker('./worker定时器.js')
script>
// worker定时器.js
var startTime = new Date().getTime();
var count = 0;
setInterval(function(){
    count++;
    console.log(count + ' --- ' + (new Date().getTime() - (startTime + count * 1000)));
}, 1000);

输出结果:
JS定时器不准及解决方案_第3张图片

你可能感兴趣的:(js)