[ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!
作为入门者来说。了解JavaScript中timer的工作方式是非常重要的。通常它们的表现行为并非那么地直观,而这是由于它们都处在一个单一线程中。让我们先来看一看三个用来创建以及操作timer的函数。
var id = setTimeout(fn, delay);
- 初始化一个单一的timer,这个timer将会在一定延时后去调用指定的函数。这个函数(setTimeout)将返回一个唯一的ID,我们能够通过这个ID来取消timer。
var id = setInterval(fn, delay);
- 与setTimeout类似,仅仅只是它会持续地调用指定的函数(每次都有一个延时),直到timer被取消为止。
clearInterval(id);, clearTimeout(id);
- 接受一个timer的ID(由上述的两个函数返回的),而且停止timer的回调事件。
要弄明确这个定时器内部是怎么工作的,有一个非常重要的概念须要被提出来:
1 定时器延迟是不准确的(guaranteed).由于全部的javascript 浏览器代码仅仅有一个单线程运行,而且那些异步事件(如鼠标点击事件,和定时器)仅仅会在出现线程空暇的时候去会运行。这有一个图表演示。例如以下:
这里有非常多信息在这个图中须要去理解。可是全然理解它之后。你会对javascript中异步机制有一个清楚的认识。
这个图是一维的:
垂直方向我们用毫秒单位来标记这个时间。这个蓝色的方块代表这个正在被运行的javascript代码。比如,这第一个被运行的javascript代码大约花了18毫秒,这个鼠标事件块大约花费了11毫秒,等等。
由于javascript 引擎永远仅仅会执行一个片段的代码在同一个时间(由于这个单线程机制),那么这时每个代码块将会堵塞(blocking)别的异步事件的执行。
这意味着当一个异步事件被调用(比如当一个鼠标点击,一个定时器触发firing,或者一个xmlhttprequest 过程完毕),它将会被增加到队里。并延迟运行(至于详细怎样被入到队列中,不同的浏览器有不同的实现。我们这里仅仅考虑简单的情况)
从一開始,在第一个javasript中,有两个定时器被初始化了: 一个10 毫秒的 setTimeout时间和一个10 毫秒的setInterval事件(这里注意,只不过初始化,亦或叫作定义)。
由于这个定时器開始的时间和位置。导致它们在第一个javascript块完毕前就已经真正被调用(这里的调用,并不是直接运行,这里须要注意,能够理解为仅仅是准备调用,把该回调方法增加到队列)了。
注意,不管怎么样(however)。定时器都不会立马运行(由于线程没有空暇的原因,它没办法直接运行)。
相反。这个被延迟的方法会被增加到队列中,在某个能够运行的时刻(线程空暇的时刻)运行。
另外一点,在第一个javascript块中。我们能够看到另一个鼠标事件被触发了。这个javascript 回调方法被关联到一个异步事件 (没人知道用户什么时候做这个动作。所以它被觉得是异步的),这个异步事件也不会立马运行,和上面的定时器一样。也会被增加到队列中。
在第一个javascript 块运行结束之后,javascript 引擎就会立马问一个问题: 还有什么在等待被运行的代码么? 那么这个时间,有一个鼠标事件回调和定时器回调同一时候在等待。这个浏览器立即挑选一个(从图中看。是鼠标事件回调)立马运行。这个定时器继续等待,直到下一个可能的时刻。
注意一点:在这个这个鼠标事件处理函数正在被运行的同一时候,第一个interval 回调函数也会调用。
正如前面提到的定时器一样,它的回调方法会被增加到队列中。
然而。注意当这个interval再一次被调用(这个时候这个定时器的回调方法正在被运行)。那么这个时候。这个interval 的回调方法将会被删除(drop)。
假设因为主线程须要运行非常长时间的代码块,导致你在队列中增加了非常多个回调方法,那么当这个主线程结束之后,一连串的回调函数连续运行没有间隔,直到结束。比較好的做法,是临时让浏览器歇息等待一会。让队列中没有Interval回调。
我们在看到一些情况:在第三个interval 回调方法触发的时候。inteval自身正在运行(这里应该是下在运行第二个interval没有结束)。这里给我们展示了一个重要的信息:
interval 不会去关心当前的线程如今运行什么,它们会把自己的回调方法增加到队列中在不论什么情况下,即使它会让两个间隔的回调方法之间的时间降低。
最后,在第二个interval(图中应该是第三个,这里应为中间有一个被drop掉了)被 运行完之后,javasript引擎中已经没有东西能够用来运行了。
这也就是说。浏览器如今正在等一个新的异步事件须要去触发(occur)。在第50毫秒的时候,再一次触发了inteval回调。
这个时候。已经没有东西去堵塞它的运行。所以它增加到队列中之后就立马运行了。
接下来,让我们看一个样例更好的理解setTimeout与setInterval的差别:
setTimeout(function(){
/* Some long block of code... */
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){
/* Some long block of code... */
}, 10);
这两段代码可能在功能的实现上很的相似。不经意一看,他们是全然一样的。
尤其是这个setTimeout代码会在上一个回调函数运行之后至少隔10毫秒再运行一次回调方法(它可能会超过10毫秒,但不会少于10毫秒)。可是setInteval 却会尝试10毫秒就运行一个回调函数,不会去管上一个回调是什么时候运行的。
These two pieces of code may appear to be functionally equivalent, at first glance, but they are not. Notably the setTimeout code will always have at least a 10ms delay after the previous callback execution (it may end up being more, but never less) whereas
the setInterval will attempt to execute a callback every 10ms regardless of when the last callback was executed.
这里有一些东西是我们从这里学到的,做一个总结:
1 javascript引擎只唯独一个单线程,正在运行的异步事件会增加到队列等待。
2 setTimeout与setInterval 是运行异步回调方法从根本上不一样的。
3 假设一个须要马上运行的定时器被堵塞了。它将被延迟运行。知道下一次线程空暇(那么被延迟的时间会超过定时器定义的时间)
4 interval 可能会没有延迟的连续运行回调方法,假设主线程了运行一个足够长的代码(比定时的延迟长)
全部的这些都是很重要的知识对于了解javascript引擎是怎样工作的。特别是对于大数量的回调事件发生的时候,为我们建立更好的应用代码建立好的基础。
----------------------------------------------------------------------------------------------------
原文出自jQuery的作者John Resig。
地址:http://ejohn.org/blog/how-javascript-timers-work/#postcomment
[ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!的更多相关文章
- python中实现定时器Timer
实现定时器最简单的办法是就是循环中间嵌time.sleep(seconds), 这里我就不赘述了 # encoding: UTF-8 import threading #Timer(定时器)是Thre ...
- Python--day41--threading中的定时器Timer
定时器Timer:定时开启线程 代码示例: #定时开启线程 import time from threading import Timer def func(): print('时间同步') #1-3 ...
- Java中的定时器Timer
java.util.Timer是一个实用工具类,该类用来调度一个线程,使线程可以在将来某一时刻开始执行. Java的Timer类可以调度一个线程运行一次,或定期运行. java.util.TimerT ...
- 线程中的定时器Timer类
Timer 定时器 几分钟之后执行一个任务. 创建了一个定时器相当于开启了一条线程,TimerTask相当于一个线程的任务.内部使用wait/notify机制来实现的. 用法非常的简单 就足以里面的 ...
- Swoole 中毫秒定时器(Timer)的使用
间隔定时器, tick 定时器会持续触发,直到调用 clear() 清除为止. $timer = Swoole\Timer::tick(3000, function (int $timer_id, $ ...
- javascript中的定时器
本文地址:[http://www.xiabingbao.com/javascript/2015/04/20/javascript-timer/] 在以前的文章[javascript中的定时器]中,简单 ...
- 浅谈JavaScript中的定时器
引言 使用setTimeout()和setInterval()创建的定时器可以实现很多有意思的功能.很多人认为定时器是一个单独的线程(之前我也是),但是JavaScript是运行在单线程环境中的,而定 ...
- 【JavaScript】JavaScript中的Timer是怎么工作的( setTimeout,setInterval)
原文(http://www.yeeyan.org/articles/view/luosheng/24380) 作为入门者来说,了解JavaScript中timer的工作方式是很重要的.通常它们的表现行 ...
- 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply
一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...
随机推荐
- CMS系统简介(从简介到使用)
CMS系统简介 1.简介 CMS是Content Management System的缩写,意为"内容管理系统". 在中国互联网的发展历程中,一直以来默默地为中国站长提供动力的CM ...
- Tuples as return values
Strictly speaking, a function can only return one value, but if the value is a tuple, the effect is ...
- 《剑指offer》数值的整数次方
一.题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 二.输入 double base, int exponent 三.输出 b ...
- 51Nod 活动安排问题(排序+优先队列)
有若干个活动,第i个开始时间和结束时间是[Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个教室? Input 第一行一个正整数n (n <= 10000)代表活动的 ...
- CentOS 7.4 安装 网易云音乐
CentOS 7.4 安装 网易云音乐 本文包含: 安装dnf 编译gcc 5.4.0 安装各种包 安装网易云音乐贯穿全局; 安装环境: CentOS 7.4, kernel3.10.0, gcc4. ...
- CentOS7-1810 系统Samba配置说明
Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件.SMB(Server Messages Block,信息服务块)通信协议是微软(Microsoft)和英特尔(Intel)在198 ...
- echarts 初始化失败问题。
dom 实例容器,一般是一个具有高宽的div元素. 注:如果div是隐藏的,ECharts 可能会获取不到div的高宽导致初始化失败,这时候可以明确指定div的style.width和style.he ...
- 【转载】GitHub详细教程
1 Git详细教程 1.1 Git简介 1.1.1 Git是何方神圣? Git是用C语言开发的分布版本控制系统.版本控制系统可以保留一个文件集合的历史记录,并能回滚文件集合到另一个状态(历 ...
- 对spring默认的单列模式的理解
我想大部分朋友对spring的单例模式都比較了解. 什么叫单例模式呢,顾名思义就是无论有多少个请求,都仅仅生成一个实例. 比方在spring中a,b请求都在调用同样的bean ,他们都是调用的同一个b ...
- shu_1171 十->二进制转换(输入输出控制)
cid=1079&pid=19">http://202.121.199.212/JudgeOnline/problem.php?cid=1079&pid=19 分析:主 ...