[ 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类型的数据 ...
随机推荐
- 获取当前最上层controller
- (UIViewController *)topViewController { UIViewController *resultVC; resultVC = [self _topViewContr ...
- 搭建Mysql双机热备 (主从同步)
准备两台centos7主机:10.0.18.132 master 10.0.18.136 slave 先把selinux关闭,iptables关闭 或者添加端口 132 master安装好Mysq ...
- [湖南师大集训2018 7 26] hunger 解题报告 (SPFA)
饿 (hungry.pas/c/cpp) [背景描述] 给出
- CSS提高渲染速度的写法
写CSS的习惯,决定页面渲染速度的快慢,这一点在脑残的IE里更加明显.养成良好的习惯,乃至形成规范,会让你的页面更快速的加载,用户体验度更高,下面是零度逍遥总结的一些提高CSS渲染速度的写法,供大家参 ...
- fullpage中大的图片超过一屏怎么在手机端滑动显示?
fullpage中大的图片超过一屏怎么在手机端滑动显示?(设置overflow电脑端是会出现滚动条的,但是在手机端不出现滚动条,图片也不可左右滑动显示) var $window = $(window) ...
- net实现ping的方法
class ServicePinger { private static readonly ILog log = LogManager.GetLogger(typeof(ServicePinger)) ...
- Future模式 总结
future模式解决异步代码的组织(混入)问题: 类似的解决方案: 1.网络响应的block: 2.SDImageview的自组织.代理模式: 3.顶层响应机制的协议机制:
- HTML标签和文档结构
HTML标签与文档结构 HTML作为一门标记语言,是通过各种各样的标签来标记网页内容的.我们学习HTML主要就是学习的HTML标签. 那什么是标签呢? #1.在HTML中规定标签使用英文的的尖括号即` ...
- AWK行处理的用法实例
第一节 awk的工作流程及基础用法 awk操作符会先检索文件的行信息,然后在行信息里找需要的内容. Awk的默认分割付是空格,awk '/模式/{print $1,$2}' file ##模式的位置可 ...
- 20180929 北京大学 人工智能实践:Tensorflow笔记02
https://www.bilibili.com/video/av22530538/?p=16 https://www.bilibili.com/video/av22530538/?p=14 (完)