JavaScript中的计时器原理
理解John Resig 在 How JavaScript Timers Work。
原理分析
timer(setInterval,setTimeout)有一个很重要的概念,时间延迟的长短是不稳定的。因为所有的javascript都是在单一线程中执行,那些异步的事件(比如说鼠标点击,或者timer)只在执行期出现空闲的时候才会运行。下图能很好的说明这个情况。

此例中有三个异步事件,鼠标点击,setTimeout,setInterval。
先介绍一下这个图的构成,左侧以10为间隔的横杠是以ms为单位从上至下的时间轴,蓝色的圆角正方形代表正在执行的代码块(这由单线程本质决定,javascript代码是以块运行的)。就比如,第一个模块执行了一些javascript代码,时间约为18ms,第二个模块鼠标点击后执行的函数花了约11ms。
下面我们详细解释这个图的运行流程和原理。
从上开始,在3ms(都是近似值)的位置执行了setTimeout(fn,10ms),然后它计时器开始计时;7ms时点击事件触发,立即添加点击回调函数到队列中;10ms执行setInterval(fn,10ms),它的计时器开始计时。下面到13ms时,这时3ms的setTimeout已经计时完毕,触发,它的fn回调函数添加到队列中。第一个块执行完毕。
此时我们的队列中堆积了我们将要执行的回调函数。依次为鼠标点击回调函数,setTimeout回调函数,取在前的,第二个的代码块将要执行的是鼠标点击的回调函数。开始执行第二个块,运行到20ms时,setInterval事件触发,回调函数添加到队列中。第二个块执行完毕。
此时我们的队列中有setTimeout,setInterval回调函数。下面执行setTimeout的回调函数。注意!到30ms时,setInterval事件又一次触发,在队列里有相同的回调函数时,这个新的setInterval回调函数会被浏览器忽略掉。第三个块执行完毕。
此时我们的队列里只有setInterval回调函数,下面执行setInterval的回调函数。到40ms时,setInterval事件触发,使得刚为空的队列里又多了一个setInterval回调函数。第四个块执行完毕。
此时我们的队列里有setInterval回调函数,执行setInterval回调函数。到结束都没产生任何下面要执行的代码。第五个模块完毕。
到50ms时,触发setInterval,队列里添加它的回调函数,因为目前没有任何代码块在执行,所以队列的代码直接执行。
三个异步事件的执行情况:
鼠标点击7ms触发,18ms才执行。
setTimeout,3ms开始,13ms触发,29ms才执行回调函数。
setInterval,10ms开始,20ms触发,30ms触发被丢弃,36ms执行回调函数;40ms触发,41ms执行回调函数;50ms触发,50ms执行回调函数。
下面给出setTimeout的测试实例
function a() {
setTimeout(function(){console.log(1)},0)
console.log(2)
}
a()//
//
function(){console.log(1)}被放在了一个下一个块中。
下面是对上述原理的总结
- JavaScript引擎只有一个线程,这使得异步事件必需列队等待执行。
setTimeout一定会和setInterval在如何执行代码上有着本质地区别。- 如果一个timer在将要执行的时候被阻塞,它将会等待下一个时机(比预期的延时要长)。
- 如果interval的执行时间较长(比指定的延时长),那么它们将连续地执行而没有延时。
原理利用
先简单讲一下在javascript中,假如大量修改DOM的操作,在内存富裕的情况,DOM会操作被分成最小片,约莫两三个操作,然后在浏览器渲染一次页面。而在内存吃紧的情况,浏览器会将许多DOM操作合并到一起,再渲染页面,以提高效率,而我们的js操作
一时没找到很好的实例,
JavaScript中的计时器原理的更多相关文章
- JavaScript中new实现原理
JavaScript中new实现原理 1.创建一个空对象 obj 2.将该对象 obj 的原型链 __proto__ 指向构造函数的原型 prototype, 并且在原型链 __proto__ 上设置 ...
- JavaScript 中 this 的原理
一.问题 学习 JavaScript 其中一个标志就是理解下面两种写法,会输出有不一样的结果. var obj = { foo: function () {} }; var foo = obj.foo ...
- javaScript中的闭包原理 (译)
这篇文章通过javaScript代码解释了闭包的原理,来让编程人员理解闭包.它不是写给大牛或使用功能性语言进行编程的程序员的.一旦意会了其核心概念,闭包理解起来并不难.然而,你不可能通过阅读任何有关闭 ...
- javascript中的计时器
javascript中的定时器有两种:一种是一次性定时器,一种是可以持续使用的定时器: 1:一次性定时器setTimeout(a,b):兼容ie的任何版本 该方法接受两个参数,第一个是要执行的代码,第 ...
- 剖析Javascript中forEach()底层原理,如何重写forEach()
我们平时用的forEach()一般是这样用的 var myArr = [1,5,8] myArr.forEach((v,i)=>{ console.log(v,i) })//运行后是这样的1 0 ...
- JavaScript中this对象原理简洁说明
今天看了阮一峰大神的博客文章:JavaScript 的this原理,把纠结很久的this的指向终于理解清楚了 原文:http://www.ruanyifeng.com/blog/2018/06/jav ...
- JavaScript中的继承(原型链)
一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...
- 领悟 JavaScript 中的面向对象
JavaScript是基于对象的语言,我们可以使用面向对象的思想去开发js代码. JavaScript是基于对象的语言. 可以使用面向对象的思想,但是不少人对这一点理解得并不全面. 在 JavaScr ...
- JavaScript中this的工作原理以及注意事项
在JavaScript中,this 的概念比较复杂.除了在面向对象编程中,this 还是随处可用的.这篇文章介绍了this 的工作原理,它会造成什么样的问题以及this 的相关例子. 要根据this ...
随机推荐
- 【POJ 2823 Sliding Window】 单调队列
题目大意:给n个数,一个长度为k(k<n)的闭区间从0滑动到n,求滑动中区间的最大值序列和最小值序列. 最大值和最小值是类似的,在此以最大值为例分析. 数据结构要求:能保存最多k个元素,快速取得 ...
- Median of Two Sorted 求两个有序数组的中位数
中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包 ...
- 集装箱学习(两):动手模拟AOP
简单的说,Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 上文已经介绍模拟IoC实现,这篇文章来动手模拟AOP. AOP简述 面向对象强调"一切皆是对象&quo ...
- Android官方技术文档翻译——Ant 任务
本文译自Android官方技术文档<Ant Tasks>,原文地址:http://tools.android.com/tech-docs/ant-tasks. 由于是抽着时间译的.所以这篇 ...
- Web堡垒机
最近研究了一下开源的web堡垒机,涉及两个,一个是gateone(python):一个是Web SSH Proxy(java),简单的对后者进行了改造,使其在登录与linux系统交互的时候,不需要使用 ...
- C#运用实例.读取csv里面的词条,对每一个词条抓取百度百科相关资料,然后存取到数据库
第一步:首先需要将csv先装换成datatable,这样我们就容易进行对datatable进行遍历: /// 将CSV文件的数据读取到DataTable中 /// CSV文件路径 /// 返回读取了C ...
- pixel像素与物理像素
- OC——NSString的常用方法
NSString *str1 = @"BeiJing"; NSString *str2 = @"beijing"; //全部转为大写 NSLog(@" ...
- HDU 3030 - Increasing Speed Limits
Problem Description You were driving along a highway when you got caught by the road police for spee ...
- 搜索+剪枝——运筹帷幄 (road.cpp)
运筹帷幄 (road.cpp) [题目描述] 刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行. 已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表 ...