JavaScript的定时器是如何工作的
理解JavaScript定时器工作原理对于学习JavaScript非常重要。因为JavaScript是单线程运行的,定时器使用场合少,不是很直观。下面通过三个函数来学习JavaScript如何定义,操作及销毁一个定时器。
- var id = setTimeout(fn, delay); - 定义一个定时器,在指定时间delay后调用函数fn。函数返回一个唯一的标识ID,如果不需要使用这个定时器可以用这个取消。
- var id = setInterval(fn, delay);- 类似setTimeout,但是会每隔指定时间delay调用指定函数fn,直至取消这个定时器。
- clearTimeout(id);clearInterval(id); -这两个函数接受一个标识ID(分别对应上面两个函数返回的ID),停止定时器的回调。
要理解定时器如何工作,首先要弄清楚一个概念,定时器的回调函数不能保证在指定时间delay一定执行。由于浏览器中的所有JavaScript都在单线程上执行,因此异步事件(例如鼠标单击和计时器)仅在执行中存在同步时间执行完有空缺时才运行。参考下图:
这张图里面包含很多信息,要想理解他们需要首先理解JavaScript异步运行机制。这张图中垂直方向上有时间刻度,以毫秒为单位,蓝色部分表示正在执行的JavaScript事件。例如,第一块JavaScript执行大约18毫秒,Mouse Click Callback大约执行11毫秒,后面以此类推。
由于JavaScript是单线程的,不能同时执行两段JavaScript代码,所以上面的蓝色的”块“都是在上一个块执行完才能执行下一个块。这意味这当一个异步任务(例如,点击鼠标事件,定时器,ajax访问)出现的时候,它将被放入到异步队列(放入队列的方式和浏览器有关,不同浏览器有不同的实现)并随后执行。
首先,在第一个代码块中,JavaScript代码中首先出先两个定时器:10ms Timer starts,10ms Interval starts。这两个定时器的回调函数何时执行取决于第一个代码块的所有代码何时执行完。请注意,由于单线程的原因,它不会立即执行。
同时,在第一个代码块里,还有一个鼠标事件Mouse Click Occurs,和上面的定时器一样,这个异步事件(点击鼠标这种用户交互是异步执行的,因为JavaScript不知道用户什么时候会点击鼠标)的回调不会立即执行,而是放在异步队列里排队等待执行。
在初始的代码块执行完毕之后,浏览器随即开始轮询这个异步队列:有那些操作等待着被执行呢?在这个例子中,鼠标点击。浏览器会选择一个立即执行(这里是鼠标点击的回调时间)。定时器会等待指定的时间delay,然后执行。
注意点击鼠标回调事件在第一个事件循环,定时器回调在随后的循环中处理。但是,在后面的事件循环中(在执行定时器处理程序时),setTimeout定时器回调函数就会被抛弃,不再执行了。如果在多个定时器之后有一大段同步任务执行,则同步任务执行完之后这些定时器回调会被立即执行,没有延迟(这个延迟可能很小,就是事件循环的间隔),直至完成。浏览器倾向于等到没有更多的异步任务被加入到异步任务队列中再开始执行。
实际上,我们可以看到在事件循环本身正在执行的同时触发了第三个回调的情况。 这向我们显示了一个重要的事实:事件循环不关心当前正在执行的内容,它们会不加区分地排队,即使这意味着从触发事件,到满足条件执行回调函数之间,有一部分事件被浪费掉了。
最后,在第二个事件回调完成执行之后,我们可以看到JavaScript引擎没有执行的剩余内容。 这意味着浏览器现在等待新的异步事件发生。 当间隔再次触发时,我们在50ms处获得此值。 但是,这次没有任何任务阻止它的执行,因此它自己立即触发。
让我们看一个示例,以更好地说明setTimeout和setInterval之间的差异。
setTimeout(function(){
/* Some long block of code... */
setTimeout(arguments.callee, 10);
}, 10); setInterval(function(){
/* Some long block of code... */
}, 10);
两者的不同之处在于setTimeout在在10毫秒的delay之后执行代码(只会多余10毫秒,绝不会少),setInterval则在每隔10毫秒的延迟时执行回调代码,不管上次的回调是否已经执行完。
好了,本文中介绍的一些要点,现在回顾一下:
- JavaScript引擎在运行时只有一个线程,从而迫使异步事件排队等待执行。
- setTimeout和setInterval在执行异步代码的方式上不同。
- 如果定时器被阻止立即执行,它将延迟到下一个可能的执行点(比所需的延迟时间更长)。
- 如果定时器延迟的事件足够长,则在到点后会立即执行,没有延迟。
所有这些都是非常重要的基础知识。 了解JavaScript引擎的工作原理,尤其是在通常发生大量异步事件的情况下,为构建高级应用程序代码奠定了良好的基础。
来源:https://johnresig.com/blog/how-javascript-timers-work/
本文是John Resig很早的一篇文章,通过setTimeout,setInterval两个函数的比较,可以了解JavaScript事件循环机制。
JavaScript的定时器是如何工作的的更多相关文章
- JavaScript中定时器的暂停和继续
对于JavaScript的定时器来说没有严格意义上的暂停和重启,只有清除停止,但是可以通过一些‘障眼法’实现 allChild[index].onclick = function(){//当点击目标且 ...
- day27—JavaScript实现定时器及其应用案例
转行学开发,代码100天——2018-04-12 JavaScript中定时器有两种,分别是setInterval和setTimeout;其用法如下: 开启: setTimeout("fun ...
- Javascript中定时器的使用方法
Javascript中定时器的使用方法 1.间隔定时器(每隔一段时间执行一次代码) 格式:setInterval(函数,时间) //时间单位是毫秒,每隔设置的时间执行函数里的内容一遍(一直执行) // ...
- JavaScript中定时器
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务. setTimeout() ...
- 理解JavaScript的定时器与回调机制
定时器方法 JavaScript是单线程的.虽然HTML5已经开始支持异步js了. JavaScript的setTimeout与setInterval看起来就像已经是多线程的了.但实际上setTime ...
- Linux驱动技术(七) _内核定时器与延迟工作
内核定时器 软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行.实际上,时钟中断处理程 ...
- JavaScript基础 -- 定时器
js 定时器有以下两个方法: setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭. set ...
- JavaScript 之 定时器
JavaScript 里面有两个定时器:setTimeout() 和 setInterval() . 区别: setTimeout():相当于一个定时炸弹,隔一段时间执行,并且只会执行一次就不在执行了 ...
- JavaScript clearInterval定时器失效原因
检查下是不是setInterval重复执行(两次以上<!-- 文件上传板块 --> <div id="adUploadWindow" class="ea ...
随机推荐
- Java开发中的23中设计模式详解(一)工厂方法模式和抽象工厂模式
一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...
- Ajax自我总结
一念起.万水千山皆有情. 一念灭.沧海桑田已无心. ------ 随记 本文主要针对ajax原理介绍,很少涉及实例,主要用于对知识的梳理总结,方便以后学习和查询... Ajax 一.Ajax是 ...
- Python 图形验证码库、二维码库的使用
1. 图形验证码库 captcha # 引入图形库 from captcha.image import ImageCaptcha # 获取图像对象 image = ImageCaptcha(width ...
- python中生成器及迭代器
列表生成式 列表生成式是python内部用来创建list的一种方法,其格式形如: L = [x*8 for x in range(10)] print(L) 此时会得到结果:[0, 8, 16, 24 ...
- Scrapy爬虫day2——简单运行爬虫
设置setting.py 修改机器人协议 ROBOTSTXT_OBEY = False 设置User-Agent DEFAULT_REQUEST_HEADERS = { 'Accept': 'text ...
- [考试反思]0820NOIP模拟测试27:幻影
注:某让我把“傻孩子”三个字全部删掉了语法不通之处自行脑补(这句本身就语法不通) skyhAK 我和以及milk_feng220 还真的没有考虑过如果我考前3的话这个颜色该怎么表示(自从不粘排行榜以来 ...
- 连接xshell 时 连不上的问题
最近这一周由于自己的xshell突然连接不到虚拟机,在网上找了很多种方法也没能解决,以至于自己在学习很多知识的时候都没能很好的去验证,去尝试.最后在求助大佬的时候终于将xshell重新连接到了虚拟 ...
- java多线程回顾3:线程安全
1.线程安全问题 关于线程安全问题,有一个经典案例:银行取钱问题. 假设有一个账户,有两个线程从账户里取钱,如果余额大于取钱金额,则取钱成功,反之则失败. 下面来看下线程不安全的程序会出什么问题. 账 ...
- go-micro+php+consul简单的微服实现
首先我们用go-micro构建一个服务.(关于go-micro的使用可以参照官方实例或者文档) //新建一个微服务 micro new --type "srv" user-srv ...
- 理解Spark运行模式(三)(STANDALONE和Local)
前两篇介绍了Spark的yarn client和yarn cluster模式,本篇继续介绍Spark的STANDALONE模式和Local模式. 下面具体还是用计算PI的程序来说明,examples中 ...