一、通过定时器我们可以间隔设定时间重复调用某个函数,利用这个特性,我们可以做很多事,例如,12306上的每间隔5秒查询自动查询一次余票,简单动画的实现等等

二、定时器的格式:

  定时器有两种格式,分别是setInterval(func, time) 和 setTimeout(func, time),这两个有一些区别

  1、setInterval(func, tine);

    (1)、 此定时器操作是这样的,解释到该语句时,是要间隔time时间后第一次执行func函数,间隔time时间后再次执行func函数,重复上述...

      来个demo理解一下吧:

    

 var count = 0;
var print = function () {
console.log(count++);
}
// 每间隔1秒调用一次print函数,所以带引结果应该是从0,1,2...一直打印
setInterval(print, 5000);

    P.S. 我们在setInterval()中传递函数时,我们一般用个匿名函数包裹一下,然后再匿名函数中执行我们要调用的函数,这样我们可以在匿名函数中进行更多操作,更灵活一些,如下

  

     var count = 0;
var print = function () {
console.log(count++);
}
// 每间隔1秒调用一次print函数,所以带引结果应该是从0,1,2...一直打印
setInterval(function () {
print();
}, 1000);

    (2)、如何停止计时器?

      setInterval有个返回值,我们获取其返回值后,调用clearInterval(返回值), 即可停止计时器,如下demo

   

    var count = 0;
// 间隔1s打印一次cunt,当count为5时结束定时器,所以打印结果为 0, 1, 2, 3, 4
var timer = setInterval(function () {
count === 5? clearInterval(timer) : console.log(count++);
}, 1000);

   

   2、setTimeout()

      (1)、这个和上边那个定时器用法一样,都是传函数和时间间隔,但运行时操作是不同,这个是间隔设定时间后,调用我们传入的函数,然后就结束了,所以和上边那个区别在于上边那个是多次,而这个只有一次。

    

// 间隔1s后带引setTimeout, 所以打印结果就是setTimeout
setTimeout(function () {
console.log('setTimeout');
}, 1000);

       (2)、停止计时器,setTimeout()也有返回值,我们获取返回值,然后执行clearTimeout(返回值),即可停止setTimeout()计时器.

       (3)、利用setTimeout()来模拟setInterval()

     原理很简单,就是递归,在函数内不断的停止计时器,再添加计时器,达到重复的目的,不多说,直接上demo:

     

var count = 0;
var timer = null;
function print() {
// 每次添加定时器前,移除前一个定时器
clearTimeout(timer);
//函数执行的语句
console.log(count++);
        // 添加定时器
  
        timer = setTimeout(function () {
                print();
}, 1000);
        
      // 循环结束条件
if(count == 10) {
clearTimeout(timer);
}
} 
timer = setTimeout(function () { print(); }, 1000);

    由代码我们可以看出打印结果为0~9,

   注意点:

      i、我们调用的函数内首先第一件事就是移除上一个定时器,因为上一个定时器已经没有作用了,所以要移除,然后再添加新的定时器

     ii、在函数内最好在移除完定时器后紧跟着添加定时器,为什么呢?以为如果我们遇到这样一种情况,定时器调用的函数需要执行很长一段时间,然后我们在函数最后添加定时器,最终就造成了这样一种结果,那就是间隔时间变为 (函数执行时间 + 定时器间隔时间)极大的延迟了间隔时间,这肯定不是我们想要的。

        那为什么添加到函数前面就没这种情况了,因为在函数执行后首先就是移除上一个计时器,然后添加新的计时器,这时计时器就开始计时了,而函数正在主线程中被执行,经过计时器设定间隔时间后,将新添加的计时器函数添加到js执行队列中,等主线程的函数执行完毕后,主线程空闲,则直接执行js执行队列中等待的计时器函数。这就大大减少了函数执行时间的影响,因为定时器间隔计时和函数执行时间同时进行了,而不是函数执行完再进行计时器的间隔,这就使间隔时间尽量的接近计时器设定的间隔时间。 

 

三、计时器执行原理和单线程:

  1、我们都知道js语言是单线程的,那单线程是什么意思呢?那就是‘JavaScrip引擎是单线程运行的,浏览器无论什么时候都有且只有一个主线程在执行JavaScript程序’

  2、js执行队列:由于js是运行在单线程环境的,所以线程一直是执行者同一个任务,而我们是讲各种欲执行的任务随机添加到js执行上,当主线程空闲时就会立即执行当前队首的任务。

    也可以这样理解,js执行队列是很多有着各自事务要办的人排成的长队,而线程是一个可以处理各种事务的窗口,但是该窗口一次只能办理一个人的事务,在窗口处理完当前人的事务后,窗口就处于空闲状态,然后接着办理长队队首人的事务,就这样按照长队顺序,窗口一次处理一个人的事务。而我们所见的代码执行仅仅是将该代码事务随机插入到js执行队列中排队等待而已,但因为浏览器js引擎处理事务非常快,所以给我们立即执行不用排队等待的感觉。(注意:往js执行队列插入任务时是随机插入到队列中的,并不一定是要插入到队尾)

  3、计时器工作方式:我们添加一个定时器后,在间隔我们设定时间后,将函数代码随机插入到js执行队列中,等主线程空闲时且该函数代码位于队首,才会执行函数代码。

  4、总结来说,就是在JavaScript中没有任何代码是立即执行的,只能说一旦主线程空闲则尽快执行

  5、setInteral带来的问题:

    (1)、假设使用重复定时器setInterval()定时器,然后添加的函数在线程需要执行很长时间,而重复定时器设定的间隔时间远远小于该函数执行时间,则在该函数执行期间,该定时器代码会被多次添加到js执行队列等待,这就导致第一次函数执行结束后之后,之前多次添加的函数代码会连续执行而没有间隔,并且第一个函数开始执行需要等主线程空闲才行,所以其第一次的间隔时间也不一定是我们设定的。(因为在上一个函数执行时多个函数代码已经添加到js执行队列中,所以函数执行结束后会立刻执行已经添加的函数代码)       

    (2)、鉴于上述问题,js引擎设定了这样一条规则:当使用setInterval()时,仅当js执行队列中没有该定时器的任何其他代码实例时,才能将该定时器代码添加到js执行队列中。否则就是加入失败,重新计时。

      但此规则又带来了其他问题;

      i、某些间隔会被跳过

      ii、多个定时器代码执行之间的间隔可能会比预期的小,实际我们等待间隔大于等于我们设定的间隔时间。

    (3)所以在使用setInterval()做动画时要注意两个问题:

      i、不能使用固定步长作为做动画,一定要使用百分比: 开始值 + (目标值 - 开始值) * (Date.now() - 开始时间)/ 时间区间

      ii、如果主进程运行时间过长,会出现跳帧的现象(因为js引擎的这条规则而无法添加函数代码)

    (4)、解决:

      使用链式setTimeout(),如上演示的用setTimeout()来模拟setInterval(),即每次在函数体执行结束的最后添加延时定时器,使函数执行之间的间隔最小为我们设定的间隔时间。

第三项参考来源:http://www.cnblogs.com/dojo-lzz/p/4606448.html

 

  

      

------------------------------------------------------------------------------------------------------end

    

js之定时器的更多相关文章

  1. js延时定时器

    // 获取图片方向延时器 getImageOrientationTimer(context) { if (context.imageTimeout) return; if (context.image ...

  2. 【JavaScript基础】Js的定时器(你想看的原理也在哟)

    [JavaScript基础]Js的定时器(你想看的原理也在哟) 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 本章是经历 ...

  3. JS实现定时器

    导出:jquery.timers-1.2.js jQuery Timers提供了三个函式 1. everyTime(时间间隔, [定时器名称], 函式名称, [次数限制], [等待函式程序完成])2. ...

  4. js 关于定时器的知识点。

    Js的同步和异步 同步:代码从上到下执行. 异步:每个模块执行自己的,同时执行. js本身就是同步的,但是需要记住四个地方是异步. Js的异步   1.定时器  2.ajax   3事件的绑定  4. ...

  5. 关于js中定时器的返回值问题

    在js中,我们常常会用到定时器来处理各种各样的问题,当我们需要清除定时器的时候,我们常常会定义一个值来接受定时器的返回值,然后再把定义好的这个值写到清除定时器的括弧后面,如: var times = ...

  6. js 面向对象 定时器 046

    获取DOM对象补充 document.getElementsByTagName('div'); //获取的多个DOM对象 这种对象叫伪数组 如果想遍历此对象 通过for(var i=0; i < ...

  7. 【笔记】js 关于定时器的理解

    总所周知 js 里面的 setTimeout() 方法是用来设定某些功能在某段时间间隔之后执行的.但是今天看了高程对定时器的描述发现并不是这样. setTimeout(function(){ //.c ...

  8. js清除定时器注意点

    如何这篇文章所述:https://www.cnblogs.com/mmykdbc/p/7418575.html js多次调用创建定时器的函数,会使定时器速度越来越快,多次调用定时器的使用场景比如:监听 ...

  9. [Web 前端] 024 js 的定时器及函数

    1. Javascript 定时器 1.1 计时事件 设定一个间隔,时间到了后准时执行代码,此为"计时事件" 1.2 作用 1.制作动画 2.异步操作 1.3 定时器的类型及语法 ...

随机推荐

  1. <转>Windows平台下Makefile学习笔记(一)

    本文转自:http://blog.csdn.net/clever101/article/details/8147352 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译平台的问题(发 ...

  2. Docker镜像Export导出和Import导入

    在使用Docker时最头痛的无非无法获取仓库镜像,我们可以通过Export导出镜像备份,通过import导入镜像.导出镜像是通过容器进行导出,下面来看镜像对应的容器: root@default:~# ...

  3. JavaSE入门学习21:Java面向对象之接口(interface)(二)

    一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.j ...

  4. Memcached的LRU和缓存命中率

    缓存命中率 命中:直接从缓存中读取到想要的数据. 未中:缓存中没有想要的数据,还需要到数据库进行一次查询才能读取到想要的数据. 命中率越高,数据库查询的次数就越少. 读取缓存的速度远比数据库查询的速度 ...

  5. Unity3D性能优化之Draw Call Batching

    在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES).每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销. Unity在运行时 ...

  6. bootstrap-ui-datetime-picker插件学习

    GitHub:https://github.com/Gillardo/bootstrap-ui-datetime-picker 准备 安装:bower install --save bootstrap ...

  7. rsync客户端命令使用简介

    rsync是linux下很流行的增量备份工具,也支持本地文件(夹)复制至远程,而且支持只传输增量部分,也是一个代码(程序)发布的好工具. 基本用法如下: rsync [一堆选项] 源文件(夹) 目标文 ...

  8. onInterceptTouchEvent和onTouchEvent调用时序(转)

    onInterceptTouchEvent和onTouchEvent调用时序 onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个c ...

  9. xmlUtil 解析 创建

    http://yangzi09150915.blog.163.com/blog/static/32953487201072911410398/ package com.aibi.cmdc.webSer ...

  10. django模板加载静态资源

    1. 目录结构 /mysite/setting.py部分配置: # Django settings for mysite project. import os.path TEMPLATE_DIRS = ...