背景:

  在JavaScript中,有两种定时器:setTimeout()和setInterval();setTimeout()只执行一次定时操作,setInterval()执行无限次定时操作;但是大多数的观点均是尽可能多使用setTimeout(),多次定数操作也是十使用setTimeout()代替setInterval()。

定时器的运行原理:

  要了解这样做原因首先要知道定时器的工作方式:JavaScript语言是单线程语言,它有一个叫做执行队列的东西来决定代码的执行顺序,而定时器的作用是:在特定的时间后将代码插入到执行队列。

  这里要特别理解:定时器setTimeout(function, Interval)这里的Interval是指当Interval个单位时间过去之后将代码function插入到执行队列中,而不是过去Interval个单位时间之后执行function代码。也就说明代码的执行的时间将大于等于Interval。

setInterval()定时器存在的问题:

  1.  定时器中的某些间隔会被跳过;

  2.  定时器之间的代码间隔可能会比预期小;

  对于存在问题1的理解:如上图所示:这个例子中的第 1 个定时器是在 205ms 处添加到队列中的(即使任务队列为空,0ms实际上是达不到的,因此至少为5ms),但是直到过了 300ms 处才能够执行。当执行这个定时器代码时,在 405ms 处又给任务队列添加了另外一个副本。在下一个间隔,即 605ms 处,第一个定时器代码仍在运行,同时在任务队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中。结果在 5ms 处添加的定时器代码结束之后,405ms 处添加的定时器代码就立刻执行。

  对于存在问题2的理解:某个 onclick 事件处理程序使用 setInterval() 设置了一个 200ms 间隔的重复定时器。如果事件处理程序花了 300ms 的时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过间隔且连续运行定时器代码的情况。

个人疑惑之处:

  首先是对于setInterval的问题1,自己尝试了写演示代码,发现最后都不能得到自己想要的输出结果(最大可能是自己理解得不够深),因为不知道用什么方法捕获那个被跳过的代码。最后我发现了一个特点:其实定时器忽略某个插入代码,好像是无关紧要的,因为一般的我们插入的函数中都包含这一些操作函数,这些操作函数如果没有执行,那么参数就不会发生变化,那么就不会影响最后的输出结果。

  对于setInterval的问题2,自己写出了演示代码, 演示代码如下:

 const log = console.log.bind(console)

 const timeDelay = (delayTime) => {
let time = new Date()
// console.log(time.getTime())
while(true) {
var t1 = new Date()
if ((t1.getTime() - time.getTime()) >= Number(delayTime)) {
// console.log(t1.getTime())
break
}
}
} const func = () => {
console.log("开始执行时间:" + new Date().toLocaleTimeString())
timeDelay(6000)
console.log("结束执行时间:" + new Date().toLocaleTimeString())
} // console.log(new Date().toLocaleTimeString()) // setInterval(func, 2000)
// 开始执行时间:19:42:36
// 结束执行时间:19:42:42
// 开始执行时间:19:42:42 // 上一次的结束到下一次的开始, 间隔为0
// 结束执行时间:19:42:48
// 开始执行时间:19:42:50 // 上一次的结束到下一次的开始, 间隔为2(不太理解这里时间间隔为什么为2s)
// 结束执行时间:19:42:56
// 开始执行时间:19:42:56 // 上一次的结束到下一次的开始, 间隔为0 setTimeout(function () {
func()
setTimeout(arguments.callee, 2000)
},2000)
// 开始执行时间:19:44:45
// 结束执行时间:19:44:51
// 开始执行时间:19:44:53 // 上一次的结束到下一次的开始, 间隔为2
// 结束执行时间:19:44:59
// 开始执行时间:19:45:01 // 上一次的结束到下一次的开始, 间隔为2
// 结束执行时间:19:45:07
// 开始执行时间:19:45:09 // 上一次的结束到下一次的开始, 间隔为2

使用setTimeout代替setInterval的方法:

 let n = setTimeout(function () {
// 判断是否将操作代码插入执行队列
if (boolean) {
// 需要插入执行队列的代码
function()
}
// 判断是否进行定时器的递归
if () {
n = setTimeout(arguments.callee, interval)
}
}, interval)

  最好假如判断条件,这样方便控制整个定时器的循环

引用:

  1. JavaScript定时器及相关面试题:https://www.cnblogs.com/unclekeith/p/6443115.html

  

  

使用setTimeout()代替setInterval()的更多相关文章

  1. 深入理解定时器系列第一篇——理解setTimeout和setInterval

    × 目录 [1]setTimeout [2]setInterval [3]运行机制[4]作用[5]应用 前面的话 很长时间以来,定时器一直是javascript动画的核心技术.但是,关于定时器,人们通 ...

  2. 前端开发:setTimeout与setInterval 定时器与异步循环数组

    前端开发:setTimeout与setInterval 定时器与异步循环数组 前言: 开通博客园三个月以来,随笔记录了工作中遇到的大大小小的难题,也看过无数篇令人启发的文章,我觉得这样的环境是极好的, ...

  3. setTimeout和setInterval从入门到精通

    我们在日常web前端开发中,经常需要用到定时器方法. 前端中的定时器方法是浏览器提供的,并不是ECMAScript规范中的.是window对象的方法. 浏览器中的定时器有两种, 一种是每间隔一定时间执 ...

  4. setTimeout和setInterval定时器使用详解测试

    var len=4; while(len--){ var time=setTimeout(function(){ console.log(len); },0); console.log(time); ...

  5. setTimeout,setInterval原理

    function a() { setTimeout(function(){alert(1)},0); alert(2); } a(); 和其他的编程语言一样,Javascript中的函数调用也是通过堆 ...

  6. Javascript的setTimeOut()和setInterval()的定时器用法

    Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请 ...

  7. setTimeout和setInterval的注意事项

    精准问题 setTimeout的问题在于它并不是精准的,例如使用setTimeout设定一个任务在10ms后执行,但是在9ms后,有一个任务占用了5ms的cpu时间片,再次轮到定时器执行时,时间已经过 ...

  8. setTimeout和setInterval的区别以及如何写出效率高的倒计时

    1.setTimeout和setInterval都属于js中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直 ...

  9. setTimeout()与setInterval()

    一.setTimeout与setInterval的用法(http://www.css88.com/archives/5804) setTimeout是超时调用,javascript是一个单线程的解析器 ...

  10. setTimeout 和 setInterval

    设置定时器,在一段时间之后执行指定的代码,setTimeout与setInterval的区别在于setTimeout函数指定的代码仅执行一次 方法一: window.setTimeout(" ...

随机推荐

  1. Tunnel Warfare 线段树 区间合并|最大最小值

    B - Tunnel WarfareHDU - 1540 这个有两种方法,一个是区间和并,这个我个人感觉异常恶心 第二种方法就是找最大最小值 kuangbin——线段树专题 H - Tunnel Wa ...

  2. spring学习笔记(二)spring中的事件及多线程

    我们知道,在实际开发中为了解耦,或者提高用户体验,都会采用到异步的方式.这里举个简单的例子,在用户注册的sh时候,一般我们都会要求手机验证码验证,邮箱验证,而这都依赖于第三方.这种情况下,我们一般会通 ...

  3. 王颖奇 201771010129《面向对象程序设计(java)》第一周学习总结

    <面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com wangyingqi 程序 ...

  4. 新书《OpenShift云原生架构:原理与实践》第一章第三节:企业级PaaS平台OpenShift

    近十年来,信息技术领域在经历一场技术大变革,这场变革正将我们由传统IT架构及其所支撑的臃肿应用系统时代,迁移至云原生架构及其所支撑的敏捷应用系统时代.在这场变革中,新技术的出现.更新和淘汰之迅速,以及 ...

  5. Java Stream 流如何进行合并操作

    1. 前言 Java Stream Api 提供了很多有用的 Api 让我们很方便将集合或者多个同类型的元素转换为流进行操作.今天我们来看看如何合并 Stream 流. 2. Stream 流的合并 ...

  6. 可怕!CPU竟成了黑客的帮凶!

    本故事根据CPU真实漏洞改编 前情回顾 还记得我吗,我是阿Q,就是那个CPU一号车间的阿Q啊.如果你忘记了我,记得看看这里回忆一下哦:完了!CPU一味求快出事儿了! 自从我们车间用上了乱序执行和分支预 ...

  7. DNSlog注入学习

    之前一直有看到过DNSlog这个字眼,但一直没有好好去了解一下,最近又接触到了刚好来深入学习下 0x01 什么是DNSlog 我们都知道DNS就是将域名解析为ip,用户在浏览器上输入一个域名A.com ...

  8. web2

    0x01 <?php $miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"; funct ...

  9. 如何搭建一个WEB服务器项目(二)—— 对数据库表进行基本的增删改查操作

    使用HibernateTemplate进行增删改查操作 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出 ...

  10. 「雕爷学编程」Arduino动手做(28)——RGB全彩LED模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...