作为入门者来说。了解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) 是怎样工作的!的更多相关文章

  1. python中实现定时器Timer

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

  2. Python--day41--threading中的定时器Timer

    定时器Timer:定时开启线程 代码示例: #定时开启线程 import time from threading import Timer def func(): print('时间同步') #1-3 ...

  3. Java中的定时器Timer

    java.util.Timer是一个实用工具类,该类用来调度一个线程,使线程可以在将来某一时刻开始执行. Java的Timer类可以调度一个线程运行一次,或定期运行. java.util.TimerT ...

  4. 线程中的定时器Timer类

    Timer 定时器 几分钟之后执行一个任务. 创建了一个定时器相当于开启了一条线程,TimerTask相当于一个线程的任务.内部使用wait/notify机制来实现的. 用法非常的简单  就足以里面的 ...

  5. Swoole 中毫秒定时器(Timer)的使用

    间隔定时器, tick 定时器会持续触发,直到调用 clear() 清除为止. $timer = Swoole\Timer::tick(3000, function (int $timer_id, $ ...

  6. javascript中的定时器

    本文地址:[http://www.xiabingbao.com/javascript/2015/04/20/javascript-timer/] 在以前的文章[javascript中的定时器]中,简单 ...

  7. 浅谈JavaScript中的定时器

    引言 使用setTimeout()和setInterval()创建的定时器可以实现很多有意思的功能.很多人认为定时器是一个单独的线程(之前我也是),但是JavaScript是运行在单线程环境中的,而定 ...

  8. 【JavaScript】JavaScript中的Timer是怎么工作的( setTimeout,setInterval)

    原文(http://www.yeeyan.org/articles/view/luosheng/24380) 作为入门者来说,了解JavaScript中timer的工作方式是很重要的.通常它们的表现行 ...

  9. 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply

    一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...

随机推荐

  1. [luogu P2586] GCD 解题报告 (莫比乌斯反演|欧拉函数)

    题目链接:https://www.luogu.org/problemnew/show/P2568#sub 题目大意: 计算​$\sum_{x=1}^n\sum_{y=1}^n [gcd(x,y)==p ...

  2. POJ 3672 水题......

    5分钟写完 水水更开心 //By SiriusRen #include <cstdio> #include <iostream> #include <algorithm& ...

  3. jquery的append/prepend和after/before有什么区别呢?

    append <p> <span class="s1">s1</span> </p> <script> $(" ...

  4. asp.net网页播放MP4 出错

    通过IIS进行添加:单击[开始]→[程序]→[管理工具]→[IIS管 理器],逐步展开“本地计算机”.“网站”,在你的网站上右击,选择[属性],单击“HTTP头”选项卡→单击“MIME类型”按钮,再单 ...

  5. iOS开发——根据数组中的字典中的某一元素排序

    数组中的元素是字典,字典中的某一个元素,比如说姓名,现在需要按照姓名的首字母来排序,怎么搞? 做法很简单,在字典中加一个元素,保存姓名的首字母,然后用下面的方法排序. - (void)sortWifi ...

  6. perl异常处理

    程序脚本在运行过程中,总会碰到这样那样的问题,我们会预知一些问题并为其准备好处理代码,而有一些不能预知.好的程序要能尽可能多的处理可能出现的异常问题,本文就总结了一些方法来解决这些异常,当然perl在 ...

  7. GIMP类似于PhotoShop的开源免费软件

    首先我们先看看他的界面如何,都有哪些功能!而且它支持多种平台,可以在MacOS.Windows.Linux操作系统上使用.非常值得推荐! ​ 1.官方地址下载地址: https://www.gimp. ...

  8. python3之对本地TXT文件进行增加,删除,修改,查看功能。

    由于是初学,代码如有不足,欢迎指出! 本博客记录我的编程之路,记录所学到的知识,分享所学心得! 这是我的一个作业. 首先分析要求: 创建一个TXT文件用于存储账号与密码 实现对文件进行增加,删除,修改 ...

  9. Python 上下文(Context)学习笔记

    前言 最早接触到with语句的时候,是初学python,对文件进行读写的时候,当时文件读写一般都是用open()函数来对文件进行读写,为了防止读写的过程中出现错误,也为了让代码更加的pythonic, ...

  10. CheckBox:屏蔽setChecked方法对OnCheckedChangeListener的影响

    对于CheckBox的OnCheckedChangeListener,有两种情况下会被触发: (1)用户点击了一下CheckBox: (2)代码中调用了setChecked(boolean check ...