在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. 013-并发编程-java.util.concurrent.locks之-AbstractQueuedSynchronizer-用于构建锁和同步容器的框架、独占锁与共享锁的获取与释放

    一.概述 AbstractQueuedSynchronizer (简称AQS),位于java.util.concurrent.locks.AbstractQueuedSynchronizer包下, A ...

  2. Cglib动态代理实现原理

    Cglib动态代理实现方式 我们先通过一个demo看一下Cglib是如何实现动态代理的. 首先定义个服务类,有两个方法并且其中一个方法用final来修饰. public class PersonSer ...

  3. C++中为何大量使用类指针

    C++的精髓之一就是多态性,只有指针或者引用可以达到多态.对象不行类指针的优点: 第一实现多态. 第二,在函数调用,传指针参数.不管你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节.如果用对 ...

  4. 多线程——interrupt方法

    测试interrupt()方法: package day_12_01_Thread; import java.util.Date; /** * 测试interrupt()方法:结束线程,但是线程还是活 ...

  5. PHP数组和字符串的处理函数汇总

    大部分数组处理函数array_chunk — 将一个数组分割成多个array_column — 返回数组中指定的一列array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的 ...

  6. DS1-3

    #include <stdio.h> #include <string.h> #define MAXSIZE 1024 double polynomial[MAXSIZE]; ...

  7. Spring MVC定时服务

    spring-mvc-config.xml <context:component-scan base-package="com.bf" ></context:co ...

  8. nginx反向代理 支持WebSocket

    WebSocket(简称WS)协议的握手和HTTP是兼容的,通过HTTP/1.1中协议转换机制,客户端可以传递名为“Upgrade” 头部信息将连接从HTTP连接升级到WebSocket连接 那么反向 ...

  9. Centos7搭建Postfix发送邮件 Connection timed out

    telent  mx1.qq.com 25 25这个端口是不加密的,不安全,qq邮箱和网易的邮箱早就不用了.采用加密的方式

  10. HTTPS安全不?

    首先,它是什么?我的理解是一开始进行SSL握手,商量好将要使用哪些加密算法来通讯,或者加密方法后使用非对称的加密方法,交互一下随机数,加上一个pre-master-secrect的,然后服务端利用私钥 ...