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);

示例输出:
示例输出
解决方案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);

输出结果:
输出结果
解决方案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);

输出结果:
输出结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值