理解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的定时器是如何工作的的更多相关文章

  1. JavaScript中定时器的暂停和继续

    对于JavaScript的定时器来说没有严格意义上的暂停和重启,只有清除停止,但是可以通过一些‘障眼法’实现 allChild[index].onclick = function(){//当点击目标且 ...

  2. day27—JavaScript实现定时器及其应用案例

    转行学开发,代码100天——2018-04-12 JavaScript中定时器有两种,分别是setInterval和setTimeout;其用法如下: 开启: setTimeout("fun ...

  3. Javascript中定时器的使用方法

    Javascript中定时器的使用方法 1.间隔定时器(每隔一段时间执行一次代码) 格式:setInterval(函数,时间) //时间单位是毫秒,每隔设置的时间执行函数里的内容一遍(一直执行) // ...

  4. JavaScript中定时器

    JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务. setTimeout() ...

  5. 理解JavaScript的定时器与回调机制

    定时器方法 JavaScript是单线程的.虽然HTML5已经开始支持异步js了. JavaScript的setTimeout与setInterval看起来就像已经是多线程的了.但实际上setTime ...

  6. Linux驱动技术(七) _内核定时器与延迟工作

    内核定时器 软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行.实际上,时钟中断处理程 ...

  7. JavaScript基础 -- 定时器

     js 定时器有以下两个方法: setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭. set ...

  8. JavaScript 之 定时器

    JavaScript 里面有两个定时器:setTimeout() 和 setInterval() . 区别: setTimeout():相当于一个定时炸弹,隔一段时间执行,并且只会执行一次就不在执行了 ...

  9. JavaScript clearInterval定时器失效原因

    检查下是不是setInterval重复执行(两次以上<!-- 文件上传板块 --> <div id="adUploadWindow" class="ea ...

随机推荐

  1. 【JAVA】可视化计算器

    import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.Actio ...

  2. 中级前端必备知识点(2.5w+月薪)进阶 (分享知乎 : 平酱的填坑札记 关注专栏 用户:安大虎)

    前端已经不再是5年前刚开始火爆时候的那种html+css+js+jquery的趋势了,现在需要你完全了解前端开发的同时,还要具备将上线.持续化.闭环.自动化.语义化.封装......等概念熟练运用到工 ...

  3. OV5640摄像头的数据处理配置流程(一)

    module RGB_init( //系统信号输入(时钟+复位) input cmos_clk_i, //模块控制时钟 input rst_n_i, //系统复位信号 //OV5640输出信号(从56 ...

  4. CPS Tester

    将测出10s的平均cps值 在窗内点击即可 github已编译程序:https://github.com/Ice-watermelon233/cps-tester #include <bits/ ...

  5. 通俗易懂了解Vue内置组件keep-alive内部原理

    1. 官方介绍及其用法 1.1 组件介绍 要想搞明白<keep-alive>组件的内部实现原理,首先我们得搞明白这个组件怎么用以及为什么要用它,关于<keep-alive>组件 ...

  6. Redis中的键值过期操作

    1.过期设置 Redis 中设置过期时间主要通过以下四种方式: expire key seconds:设置 key 在 n 秒后过期: pexpire key milliseconds:设置 key ...

  7. Python 基础 内置函数 迭代器与生成器

    今天就来介绍一下内置函数和迭代器 .生成器相关的知识 一.内置函数:就是Python为我们提供的直接可以使用的函数. 简单介绍几个自己认为比较重要的 1.#1.eval函数:(可以把文件中每行中的数据 ...

  8. 一文带你深入了解 Redis 的持久化方式及其原理

    Redis 提供了两种持久化方式,一种是基于快照形式的 RDB,另一种是基于日志形式的 AOF,每种方式都有自己的优缺点,本文将介绍 Redis 这两种持久化方式,希望阅读本文后你对 Redis 的这 ...

  9. hdu 1556 Color the ball (技巧 || 线段树)

    Color the ballTime Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  10. nyoj 33-蛇形填数 (循环,模拟)

    33-蛇形填数 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:15 submit:38 题目描述: 在n*n方陈里填入1,2,...,n*n,要求填 ...