在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害.

先看以下两看计时器

setTimeout版

function test(){
count += 1;
console.log(`第${count}次开始 ${getTime.now() - startTime} ID:${t}`); // 显示开始时间 console.log(`第${count}次结束 ${getTime.now() - startTime}`); // 显示结束时间 //count<1000 && setTimeout(test,500); //这样写没有ID
if(count<1000) t=setTimeout(test,500); //这样写没有ID
} let count = -1;
let getTime = window.performance;
let startTime = getTime.now();
var t; test(); // 300ms间隔

运行结果

误差很大,原因js是单线程,而setTimeout两次时间间隔为timer执行时间+interval延时时间,久而久之积累的误差就大了

setInterval版
function sleep(time) {
let startTime = window.performance.now();
while (window.performance.now() - startTime < time) {}
} function test(){
count++;
console.log(`第${count}次开始 ${getTime.now() - startTime}`);
// 显示开始时间
//sleep(100); // 程序滞留500ms
console.log(`第${count}次结束 ${getTime.now() - startTime}`); // 显示结束时间
count>1000 && clearInterval(t);
} let count = 0;
let getTime = window.performance;
let startTime = getTime.now(); var t = setInterval(test , 500); // 300ms间隔

最后结果:

测了两次结果差很多,可能应该是第一次我切出当前页的原因,已至getTime.now();出错,从第二个结果看,还是很精准的,但是,

第一种写法:

1
2
3
4
funciton xxx(){
//函数代码,此处执行时间约20毫秒
setTimeout(xxx,10)
}

第二种写法:

1
2
3
4
funciton xxx(){
//函数代码,此处执行时间约20毫秒
}
setInterval(xxx,10)

第一种写法中,只有执行完20ms的代码后,再等10ms才会开始下一个循环;

第二种写法中,无论有没有执行完20ms的代码,10ms后都会开始下一个循环

setTimeout优化版:

var startTime0 = new Date().getTime();
let count = 0;
let getTime = window.performance;
let startTime = getTime.now();
var t;
//setTimeout(test,500); // 300ms间隔 setTimeout(function () {
count += 1;
console.log(`第${count}次开始 ${getTime.now() - startTime}`);
// 显示开始时间
//sleep(500); // 程序滞留500ms var offset = getTime.now() - (startTime + count * 500);
var nextTime = 500 - offset;
//console.log(nextTime);
if (nextTime < 0) nextTime = 0;
console.log(`第${count}次结束 ${getTime.now() - startTime} 下次延时:${nextTime}`); // 显示结束时间
if(count<1000){setTimeout(arguments.callee, nextTime);} }, 500)

setTimeout优化后的结果

setTimeout优化说明:

1、最大的特点就是动态修正当前触发的延迟时间。

2、为什么选择setTimeout,因为setTimeout更方便调节延迟时间。

3、使用performance.now()是当前时间与performance.timing.navigationStart的时间差,以微秒(百万分之一秒)为单位的时间,与 Date.now()-performance.timing.navigationStart的区别是不受系统程序执行阻塞的影响,因此更加精准。关于performance的更多内容

4、第二个setTimeout()调用使用了agrument.callee 来获取当前实行函数的引用,并设置另外一个新定时器。这样做可以保证在代码执行完成前不会有新的定时器插入。(来自

相关链接:https://blog.csdn.net/acm765152844/article/details/51298915

js定时器优化的更多相关文章

  1. javascript定时器,取消定时器,及js定时器优化方法

    通常用的方法: 启动定时器: window.setInterval(Method,Time) Method是定时调用的js方法 Time是间隔时间,单位是毫秒 取消定时器: clearInterval ...

  2. JS定时器不可靠的原因及解决方案

    前言 在工作中应用定时器的场景非常多,但你会发现有时候定时器好像并没有按照我们的预期去执行,比如我们常遇到的setTimeout(()=>{},0)它有时候并不是按我们预期的立马就执行.想要知道 ...

  3. 应用r.js来优化你的前端

    r.js是requireJS的优化(Optimizer)工具,可以实现前端文件的压缩与合并,在requireJS异步按需加载的基础上进一步提供前端优化,减小前端文件大小.减少对服务器的文件请求.要使用 ...

  4. js性能优化-事件委托

    js性能优化-事件委托 考虑一个列表,在li的数量非常少的时候,为每一个li添加事件侦听当然不会存在太多性能方面的问题,但是当列表非常的长,长到上百上千甚至上万的时候(当然只是一个解释,实际工作中很少 ...

  5. js定时器的使用(实例讲解)

    在javascritp中,有两个关于定时器的专用函数,分别为: 1.倒计定时器:timename=setTimeout("function();",delaytime);2.循环定 ...

  6. 移动Web与js定时器暂停或不准确计时的问题解决

    PC 上的 Firefox.Chrome 和 Safari 等浏览器,都会自动把未激活页面中的 JavaScript 定时器(setTimeout.setInterval)间隔最小值改为 1 秒以上: ...

  7. js定时器 特定时间执行某段程序的例子

    定时器想必大家并不陌生吧,在本文为大家详细介绍下js中是如何实现定时器的,具体原理及代码如下. 例子: $(function(){ var handler = function(){ //www.jb ...

  8. js定时器setInterval()与setTimeout()

    js定时器setInterval()与setTimeout() 1.setTimeout(Expression,DelayTime),在DelayTime过后,将执行一次Expression,setT ...

  9. js 性能优化利器:prepack

    1. js 性能优化 js 本身是没有像 python 一样的预编译功能,更没有像 java 一样的编译功能,所以,这里所说的 js 代码预编译 只是通过工具实现的类似功能而已. 这就要提到 prep ...

随机推荐

  1. MongoDB pymongo模块 查询

    查询 mongo_db 类似于 服务器命令行的db 我们可以db.user.find() 查询 find() 需要加上列表 import pymongo mongo_client = pymongo. ...

  2. 使用python实现日志功能

    Python脚本日志系统   Python通过logging模块提供日志功能,关于logging模块的使用网络上已经有很多详细的资料,这里要分享的是怎样在实际工程中使用日志功能. 假设要开发一个自动化 ...

  3. redis.conf密码设置的问题

    requirepass是终端客户端登录需要的密码,配置在服务端 masterauth是从服务器端登录master端需要的密码,配置在从服务端

  4. IOS 键盘弹出导致的position:fixed 无效问题

    解决办法(还未测试): 只需要在中间部分外层div添加css样式position:fixed;top:50px; bottom:50px;overflow:scroll;就可以实现效果,无需插件.可拷 ...

  5. 帝国cms建站总结-(分页)

    帝国cms分页代码文件t_functions.php 代码为: <?php if(!defined('InEmpireCMS')) { exit(); } define('InEmpireCMS ...

  6. python的执行顺序

    为了区分是主动执行(如python test.py)还是被动调用(如import test),python用__name__来进行标识. 当主动执行时,__name__为__main__,当被调用时, ...

  7. golang 编译或链接 c语言动态、静态库的方法, golang 与 c语言 相互调用

    1.golang链接c静态库的方法可以见这个示例: https://github.com/atercattus/go-static-link-example https://github.com/sh ...

  8. sublime的lua插件

    1.语法检测插件~ sublimelinter sublimelinter-lua sublimelinter-luacheck 以上插件装好以后,在环境变量里面有加上lua.exe就ok了! 这个就 ...

  9. TL-WAR1200L V1.0升级软件20170609

         TL-WAR1200L_V1.0升级软件20170609.part1.rar  TL-WAR1200L_V1.0升级软件20170609.part2.rar TP-LINK WVR& ...

  10. Linux Performance 一文

    http://www.brendangregg.com/linuxperf.html Brendan D. Gregg 专注 Linux performance & tuning 许多年,其博 ...