作为入门者来说。了解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

转载于:https://www.cnblogs.com/claireyuancy/p/6956876.html

[ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!相关推荐

  1. python中实现定时器Timer

    实现定时器最简单的办法是就是循环中间嵌time.sleep(seconds), 这里我就不赘述了 # encoding: UTF-8 import threading #Timer(定时器)是Thre ...

  2. Linux内核中关于定时器Timer的应用

    2019独角兽企业重金招聘Python工程师标准>>> 在Touchscreen驱动中 1 声明  Ad7877.c (\linux-2.6.30.4\drivers\input\t ...

  3. JAVA程序设计计时器代码_Java中的定时器Timer使用示例代码详解

    一.类概述 Timer是一种定时器工具,用来在一个后台线程计划执行指定任务.它可以计划执行一个任务一次或反复多次. TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务. 二.代码 ...

  4. linux timer 回调函数,Linux内核中关于定时器Timer的应用

    在Touchscreen驱动中 1 声明 Ad7877.c (\linux-2.6.30.4\drivers\input\touchscreen):struct timer_listtimer;/* ...

  5. java线程系列---类中的定时器Timer

    常用的定时用法为:new Timer().schedule(new MyTimerTask(), 2000); 表示为:2秒之后执行MyTimerTask里的方法 new Timer().schedu ...

  6. JavaScript中的定时器详解

    前言 JavaScript 中有两种定时器: setTimeout():指定时间后执行一段代码(延迟执行). setInterval():每隔一段时间执行一段代码(间隔执行). 下面单独对两种计时器进 ...

  7. 精读《你不知道的javascript》中卷

    前言 <你不知道的 javascript>是一个前端学习必读的系列,让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaScript每一个零部件的用途.本书< ...

  8. JavaScript文件中调用AngularJS内部方法或改变$scope变量

    需要在其他JavaScript文件中调用AngularJS内部方法或改变$scope变量,同时还要保持双向数据绑定: 首先获取AngularJS application: 方法一:通过controll ...

  9. java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组之间的转换方法...

    1.java代码中fastjson生成字符串和解析字符串的方法 List<TemplateFull> templateFulls = new ArrayList<TemplateFu ...

最新文章

  1. Puppet客户端自动安装脚本
  2. 弯曲传传感器 WWW.TE.COM
  3. Salesforce 用机器学习来自动总结文本,AI+SaaS 是未来吗?
  4. mysql 字符串 空格函数_mysql中的去除空格函数
  5. ConcurrentHashMap的源码分析-数据迁移阶段的实现分析
  6. Spark精华问答 | spark的组件构成有哪些?
  7. Linux操作系统的诞生及主要特性
  8. Airbnb 面试题汇总
  9. 计算机扩容硬盘,扩容盘是什么 如何恢复真实容量【方法详解】
  10. 计算机上数字代表那个音符,音符时值
  11. php打开文件fopen函数
  12. 北大美女辞去公司副总职务创业养狗
  13. 从键盘读入3个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件1.txt中保存
  14. 高通efs_了解EFS
  15. sd卡格式化fat32格式_如何在Windows上使用FAT32格式化大于32GB的USB驱动器
  16. Photoshop Elements 2023 for mac/win(PS简化版2023)​
  17. 如何获取layui表格选中行的数据
  18. linux----------2--3----(无名)管道通信原理及管道编程实战
  19. 可汗学院 统计学习第一天
  20. Python线程详解

热门文章

  1. BZOJ.4553.[HEOI2016TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)
  2. MATLAB小记_fread的用法
  3. 使用递归算法结合数据库解析成java树形结构
  4. uploadify插件的使用
  5. POJ 1422 Air Raid (最小路径覆盖)
  6. css background size
  7. ITK读取RGB图像像素值
  8. 使用javamail发信过程中的一些问题及解决方法
  9. oracle报错ora-00200,oracle 11gR2 rac 创建database报ORA-00200错误
  10. mysql pxc测试_Mysql同步机制 - PXC 压力测试 tpcc安装及使用