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 ...
随机推荐
- 持续集成学习6 jenkins自动化代码构建
一.实验目标 二.配置 1.配置mvn构建 [root@node1 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3 ...
- [2018-01-12] laravel中的MVC
路由里面可以做所有事情,但是真正的项目当中,路由只用来接收请求,并转发给控制器的方法进行处理 首先我们先了解一下 一.app/Http/routes路由的用法: 方法一. 这种方法写完后在控制器创建方 ...
- Django学习day8——admin后台管理和语言适应
Django最大的优点之一,就是体贴的为你提供了一个基于项目model创建的一个后台管理站点admin.这个界面只给站点管理员使用,并不对大众开放. 1. 创建管理员用户 (django) E:\Dj ...
- [考试反思]0725NOIP模拟测试8
看清你是个什么东西了么? 现在看清了么?rank#15?垃圾玩意? 你什么也不是.你没有骄傲,偷懒的资格! 节节败退,永无止境,你想掉到什么样子? 你还在为了成功拿到送分的T1而沾沾自喜?只不过是勉强 ...
- CSPS_102
$\Huge % Dybala$ T1 神奇单调栈,但是有点码农,要对着对拍调很久. T2 观察到队长跑到i点之后,前面的[1,i)的点都被经过了偶数次,再次到达的时候又得被暗杀 所以通过点i的花费可 ...
- Android 开源库 GitHub 托管
本文微信公众号「AndroidTraveler」首发. 背景 之前给大家写过一篇文章 Android 上传开源项目到 jcenter 实战踩坑之路,分享了上传开源项目到 jcenter 上面的一些踩坑 ...
- jmeter-手机号验证注册登录
1.测试计划->线程组 2.首先获取需要注册的手机号,获取手机号的方式如下 (1)使用配置元件导入需要注册的手机 ·右键线程组-->配置元件-->CSV数据文件设置,如图: (2)使 ...
- 欧拉路&&欧拉回路
T1是欧拉路板子,但我不会,直接爆炸.. 这玩意就是个dfs,但我以前一直以为欧拉路只能$O(nm)$求 今天才知道可以$O(n+m)$ 欧拉路判定: 无向:起点终点为奇度点,其余偶度 有向:起点终点 ...
- MapReduce任务提交源码分析
为了测试MapReduce提交的详细流程.需要在提交这一步打上断点: F7进入方法: 进入submit方法: 注意这个connect方法,它在连接谁呢?我们知道,Driver是作为客户端存在的,那么客 ...
- web应用安全框架选型:Spring Security与Apache Shiro
一. SpringSecurity 框架简介 官网:https://projects.spring.io/spring-security/ 源代码: https://github.com/spring ...