JavaScript里面内置了两个定时器,一个是setTimeout()一个是setInterval()。下面将由浅入深来理解一下定时器的工作原理。

使用方式:

setTimeout()

setTimeout 的语法非常简单,第一个参数为回调函数,第二个参数为延时的时间。函数返回一个数值类型的ID唯一标示符,此ID可以用作 clearTimeout 的参数来取消定时器:
[html] view plaincopy print?
  1. function out(){
  2. alert("定时器");
  3. };
  4. var timeoutID = window.setTimeout(out,10000);
第一个参数可以传入多个回调函数中间以";"隔开即可,另外要注意的是函数不能加(),不能写成out();否则就会有意想不到的错误。

setInterval()

该方法使得一个函数每隔固定时间被调用一次,是一个很常用的方法。如果想要取消定时执行,和clearTimeout方法类似。
第一个方法和第二个方法的最大差别是一个是只执行一次,一个是会循环执行。
高级定时器
很多人都对JS的定时器存在普遍的误解,认为它是线程,其实JavaScript是运用于单线程的环境中的,定时器仅仅只是计划代码再未来的某个时间执行。执行时机是不能保证的,因为在页面的生命周期中,不同时间可能有其他代码在控制JavaScript线程。在页面下载完成后的代码运行,事件处理程序,Ajax回调函数都必须使用同样的线程来执行,实际上,浏览器负责进行排序,指派某段代码在某个时间点的优先级。
可以把JS想象成在时间线上运行的,当页面载入时,先执行任何包含在<script>元素的代码,在这之后,JS进程将等待更多代码执行。当进程空闲的时候,下一个代码会被触发并立刻执行。例如当点击某个按钮时,onclick事件处理程序会立刻执行,只要JavaScript进程处于空闲状态。
除了主JS执行程序外,还有一个进程空闲时候执行的代码队列,随着页面在其生命周期中的推移,代码会按照执行顺序添加到队列。
定时器对队列的工作方式是,当特定的时间过去后,将代码插入,注意添加到队列并不意味着它会马上执行,而只能说它会尽快执行,设定一个250ms后执行的定时器,不代表250ms后它会马上执行,它只会表示在150ms后被加入到队列中,如果这个时间点队列是空闲的,那么这段代码就会被执行。
[html] view plaincopy print?
  1. var timeoutID = window.setTimeout(out,10000);
  2. var btn = document.getElementById("mybtn");
  3. btn.onclick = function () {
  4. setTimeout(function () {
  5. document.getElementById("message").nodeName = "mymessage";
  6. //其它代码
  7. }, 250);
  8. }
对于定时器最要注意的是:指定的时间间隔表示何时将定时器的代码添加到队列中,而不是何时执行代码。关于这个onclick事伯处理的进程时间线请看下图:
下面展示一个简单的计时,并带有停止功能:
[html] view plaincopy print?
  1. <pre code_snippet_id="1831745" snippet_file_name="blog_20160815_3_3109891" name="code" class="html"><!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="Generator" content="EditPlus®">
  6. <meta name="Author" content="">
  7. <meta name="Keywords" content="">
  8. <meta name="Description" content="">
  9. <title>Document</title>
  10. </head>
  11. <body>
  12. <input type="button" value="开始计时!" onClick="timedCount()">
  13. <input type="text" id="txt">
  14. <input type="button" value="停止计时!" onClick="stopCount()">
  15. </body>
  16. <script type="text/javascript">
  17. var c = 0
  18. var t
  19. function timedCount() {
  20. document.getElementById('txt').value = c
  21. c = c + 1
  22. t = setTimeout("timedCount()", 1000)
  23. }
  24. function stopCount() {
  25. clearTimeout(t)
  26. }
  27. </script>
  28. </html></pre><br><br>

关于重复定时器,我们既可以使用setTimeout来重复创建就时器,也可以直接用setInterval,使用setInterval创建的定时器确保了定时器规则地插入队列中,这个方式问题在于代码可能在再次添加到队列之前还没有完成执行,可能寻到定时器重复运行好几次,而中间没有停顿,然而现在的javascript引擎很聪明,能避免这个问题,当使用setInterval时,仅当没有定时器的任何其它代码时,才将定时器代码添加到队列中,这样会确保定时器代码加入到队列的时间的间隔是为指定的间隔,请注意这只是加入队列的时间间隔,并不是执行代码的时间间隔,所以使用setInterval还是会存在两个问题:(1)某些间隔会被跳过了(2)多个定时器的代码执行间隔可能会比预期的要小。

这个例子中的第一个定时器是在205处添加到队列中,但是直到了300ms处才能够执行。当执行这个定时器代码时,在405处又给队列添加了另外一个副本,在下一个间隔,即605ms处,第一个定时器代码仍然在执行,同时在队列中已经有了一个定时器代码的实例。结果是在5ms添加的定时器代码结束之后,405处添加的定时器代码就立刻执行。
为避免这些问题,可以使用如下模式使用链式setTimeout调用:
[html] view plaincopy print?
  1. setTimeout(function () {
  2. //处理中
  3. setTimeout(arguments.callee, interval);
  4. }, interval)

关于定时器的使用技巧

给定时器调用传递参数

无论是window.setTimeout还是window.setInterval,在使用函数名作为调用句柄时都不能带参数,而在许多场合必须要带参数,这就需要想方法解决。例如对于函数hello(_name),它用于针对用户名显示欢迎信息: 
[html] view plaincopy print?
  1. var userName="jack";
  2. //根据用户名显示欢迎信息
  3. function hello(_name){
  4. alert("hello,"+_name);
  5. }
这时,如果企图使用以下语句来使hello函数延迟3秒执行是不可行的: 
window.setTimeout(hello(userName),3000); 
这将使hello函数立即执行,并将返回值作为调用句柄传递给setTimeout函数,其结果并不是程序需要的。而使用字符串形式可以达到想要的结果: 
window.setTimeout("hello(userName)",3000); 
这里的字符串是一段JavaScript代码,其中的userName表示的是变量。但这种写法不够直观,而且有些场合必须使用函数名,下面用一个小技巧来实现带参数函数的调用: 
[html] view plaincopy print?
  1. <script language="JavaScript" type="text/javascript">
  2. <!--
  3. var userName="jack";
  4. //根据用户名显示欢迎信息
  5. function hello(_name){
  6. alert("hello,"+_name);
  7. }
  8. //创建一个函数,用于返回一个无参数函数
  9. function _hello(_name){
  10. return function(){
  11. hello(_name);
  12. }
  13. }
  14. window.setTimeout(_hello(userName),3000);
  15. //-->
  16. </script>
这里定义了一个函数_hello,用于接收一个参数,并返回一个不带参数的函数,在这个函数内部使用了外部函数的参数,从而对其调用,不需要使用参数。在 window.setTimeout函数中,使用_hello(userName)来返回一个不带参数的函数句柄,从而实现了参数传递的功能。

取消定时器

一般我们取消定时器是用的
[html] view plaincopy print?
  1. clearInterval(Method);
可是读了上面的内容我们知道它是不会马上执行的,所以优化方案如下
[html] view plaincopy print?
  1. var timeout = false; //启动及关闭按钮
  2. function time()
  3. {
  4. if(timeout) return;
  5. Method();
  6. setTimeout(time,100); //time是指本身,延时递归调用自己,100为间隔调用时间,单位毫秒
  7. }

建议:最好不用setInterval,而用setTimeout的延时递归来代替interval。

setInterval会产生回调堆积,特别是时间很短的时候。

JavaScript定时器原理及高级使用相关推荐

  1. JavaScript定时器原理分析

    JavaScript中的定时器大家基本在平时的开发中都遇见过吧,但是又有多少人去深入的理解其中的原理呢?下面我们就来分析一下定时器的实现原理. 一.储备知识 在我们在项目中一般会遇见过这样的两种定时器 ...

  2. JavaScript定时器的工作原理(翻译)

    JavaScript定时器的工作原理(翻译) 标签(空格分隔): JavaScript定时器 最近在看ajax原理的时候,看到了一篇国外的文章,讲解了JavaScript定时器的工作原理,帮助我很好的 ...

  3. JavaScript 工作原理(二)-如何在 V8 引擎中书写最优代码的 5 条小技巧(译)

    From:https://segmentfault.com/a/1190000014770145 原文请查阅这里,略有删减. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScrip ...

  4. JavaScript 工作原理之二-如何在 V8 引擎中书写最优代码的 5 条小技巧(译)

    原文请查阅这里,略有删减. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第二章. 本章将会深入谷歌 V8 引擎的内部结构.我们也会为如何书写更好的 Java ...

  5. 深入探索 Qt WebEngineCore:从基础原理到高级应用与技巧

    深入探索 Qt WebEngineCore:从基础原理到高级应用与技巧 Diving into Qt WebEngineCore: From Basic Principles to Advanced ...

  6. JavaScript 工作原理之五-深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势(译)...

    原文请查阅这里,略有改动,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第五章. 现在 ...

  7. JavaScript 工作原理之十一-渲染引擎及性能优化小技巧

    原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第十一章. 迄 ...

  8. html倒计时timer,JavaScript定时器设置、使用与倒计时案例详解

    本文实例讲述了JavaScript定时器设置.使用与倒计时案例.分享给大家供大家参考,具体如下: 1.设置定时器 定时器,适用于定时执行的任务中.在BOM的window对象中,有这样的两个函数是用于设 ...

  9. 【学习笔记】 Javascript定时器

     Javascript定时器 Window对象提供的定时器功能,其基本功能是在规定的时间自定执行某个函数. 根据执行的机制,定时器又分为间歇定时器和延迟定时器. 间歇定时器:每隔一段时间执行指定函数( ...

最新文章

  1. oracle11g导出表时会发现少表,空表导不出解决方案。
  2. eclipse怎么设置字体大小非原创
  3. python gpu加速 显卡_PyTorch-GPU加速实例
  4. IOS-网络(GCD)
  5. Visual Studio 2012 和.NET Framework 4.5 快速开始的5分钟视频
  6. java面试 上传文件_字节跳动面试官,我也实现了大文件上传和断点续传
  7. dataframe scala 修改值_Spark DataFrame:提取某列并修改/ Column更新、替换
  8. 搜集访问网页历史记录软件_微软宣布OneDrive版本历史记录功能抵达Win10和macOS客户端版...
  9. Brew Command Not Found
  10. java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
  11. Python--Turtle钟表
  12. 谭浩翔c语言,严谨细致的科技尖兵丨广州市公安局黄埔区分局民警谭浩翔
  13. 渲染用计算机功耗,【IT之家评测室】满功耗 RTX 3060 笔记本 GPU 表现如何?拯救者 R9000P 实测...
  14. FastJson耗时
  15. 挂载 机械硬盘_如何在mac苹果系统下使用移动硬盘
  16. 乐视max70老款_这货是电视?超大尺寸乐视TV Max70试玩
  17. 在ubuntu下烧写映像文件到nand--基于三星210开发板
  18. 你活着的意义是什么?(灵魂拷问)
  19. 计算机b级机房建设标准,A类机房建设标准和B类机房建设标准【全国施工】
  20. 【正点原子MP157连载】第一章 Ubuntu系统安装-摘自【正点原子】【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

热门文章

  1. Kubernetes健康检查如何做?官方推荐教程
  2. 深入浅出: Java回调机制(异步)
  3. Linux:nice函数
  4. Android --- Serializable 接口与 Parcelable 接口的使用方法和区别,怎么选择?
  5. Android --- 数据库存储的是正确的时间格式(2021-06-17 21:47:23)但是在获取的时候变成了(2021-06-17T13:47:23.000+00:00)
  6. mysql 隐式锁和显示锁_锁的类型以及粒度,两段锁协议,隐式和显示锁
  7. 中国液冷数据中心发展白皮书
  8. 调研机构称明年全球数据中心基础设施支出将增长6%
  9. POE交换机应用技术知识大全
  10. 未来的数据中心(三)