前端技术分享-码匠 极客编程技术分享

您当前位于:JavaScript高级 ——> 原生JavaScript 计时器高级知识讲解

原生JavaScript 计时器高级知识讲解

2015/05/02 11:14:12 | 作者:HTML5学堂(码匠) | 分类:JavaScript高级 | 关键词:JavaScript,计时器

JavaScript 高级计时器详解

HTML5学堂:计时器这个东西,看上去很简单,但是可以拓展挖掘的东西却有很多。对于计时器的基本描述(setInterval与setTimeout)基本名词要规范,如“递归”,文字内容描述应当清晰易于理解,而不是含糊不清。对于区别,并不是仅仅说出运行上的特点,还应当能够说出如何应用以及对性能的影响。对于运行上有可能出现的问题,也能够阐述出来。

平时对计时器的阐述方式

计时器分为两类,一种是“在间隔设置了的时间之后,运行相应的函数”,即setTimeout,而另一种是“每隔一段设定的时间间隔,就运行一次相应的函数”。我们可以使用将setTimeout的代码放置到函数内,然后通过对函数的递归调用,而实现类似于setInterval的效果。

对于计时器基本阐述方法的“纠偏”

JavaScript的运行是单线程运行,因此,严格意义上来讲,上面的基本阐述当中并不是足够的严谨。应该是说,在运行本行代码的时候,将定时器的代码添加到了运行队列当中,而不是何时执行/运行代码。此时需要等到当前“事件处理程序”运行之后再去执行定时器代码。换句话说,就是,并非是设置的毫秒数后就执行定时器代码,执行的时间是有可能提前/延后的。

理解计时器的延迟和提前

为方便理解,书写一个例子。假设有如下这段函数,如果认为点击事件的处理程序需要运行200毫秒,从函数开始运行直到设置计时器代码,需要花费10毫秒,计时器设置为150毫秒后运行函数功能,那么相当于是在160毫秒的位置设置了定时器代码,而这段在200毫秒的位置才进行了执行。

  1. con.onclick = function(){
  2.     // 代码段1
  3.     // 代码段1运行10毫秒
  4.     setTimeout(move, 150);
  5.     // 设置在150毫秒,将计时器中的代码插入到队列当中
  6.     // 代码段2
  7.     // 代码段2需要运行190毫秒(注意,此处把setTimeout这句代码的执行时间假设为0)
  8. }
  9. function move(){
  10.     // 假设move函数需要运行100毫秒
  11. }

HTML5学堂 JS高级计时器

欢迎沟通交流~HTML5学堂

深入分析setInterval 引擎方面

针对setInterval,JavaScript引擎进行了处理。之所以处理,在于定时器中代码内容的执行时间有可能会大于间隔时间。也就是说,在代码被再次添加到队列之前,还没与完成执行,从而导致连续运行多次。因此,JavaScript引擎进行了相关处理,仅当队列中没有该定时器的任何其他代码实例时,才能够将定时器代码添加到队列。

由于线程方面的因素,如果使用setInterval之后,可能会造成的问题以及问题规避:1)某些间隔会被跳过;——这也就能够解释如果我们将setInterval中的时间间隔设置为1-10,然后通过位置的变化去实现滚动类效果,会发现滚动块不能像我们希望的那么快的运动。2)多个定时器的代码执行之间的间隔可能会比预期的小。

依旧举个例子:

规避问题的方法

  1. setTimeout(function(){
  2.     // 其他代码
  3.     setTimeout(arguments.callee, interval);
  4. }, interval);
  5. // 备注:interval指的是毫秒数。
  6. // 基本原理是:链式的调用setTimeout,每次函数执行时会创建一个新的定时器,第二个setTimeout调用使用了arguments.callee来获取对当前执行的函数的引用,并为它设置另一个定时器。这样做的好处是,在前一个定时器代码执行完毕之后,不会在队列中加入新的定时器代码,同时还能够没有任何缺失的间隔,从而避免连续运行。callee 属性是 arguments 对象的一个成员,他表示对函数对象本身的引用,这有利于匿名函数的递归或确保函数的封装性

HTML5学堂 JS高级计时器2
内存泄露

内联书写setInterval时,由于匿名函数被定义于全局中,不能够计时器的清除,因此很容易造成内存泄露。

计时器 总结

JavaScript引擎是单线程的,强制所有的异步事件排队等待执行。

setTimeout 和 setInterval 在执行异步代码的时候有着根本的不同。

如果一个计时器被阻塞而不能立即执行,它将延迟执行直到下一次可能执行的时间点才被执行(比期望的时间间隔要长些)。

如果setInterval回调函数的执行时间将足够长(比指定的时间间隔长),它们将连续执行并且彼此之间没有时间间隔。

欢迎沟通交流~HTML5学堂

微信公众号,HTML5学堂,码匠,原创文章,WEB前端,技术分享

HTML5学堂

原创前端技术分享

HTML5学堂,HTML5,WEB,前端,视频课程,技术视频,学习视频,面试,JS

原创视频课程

用心打造精品课程

微信小程序,决胜前端,面试题,面试题集合,前端,HTML5,真题

小程序-决胜前端

前端面试题宝库

原创书籍,学习书籍,书籍推荐,HTML5布局之路,HTML5,WEB前端

HTML5布局之路

非传统模式讲解前端