说明

在开发功能“轨迹播放”时,遇到了一个情况。

原先同事已经开发了一版,这次有个新功能:点击线上任意一点后可以从点击处重新播放。

看了一下原来的版本,发现同时使用了setTimeout和setInterval,两者配合实现点线播放。

简单结构如下

        function test() {
setInterval(function () {
console.log("interval");
//省略插值方法得到arr
(...)
play(arr);
}, 2000);
}
function play(arr) {
setTimeout(function () {
play(arr);
console.log("setTimeout");
}, 40);
}

我觉得这个结构欠妥,两个定时器配合必定会出现失误!因此重构了一版,将两个定时器改为一个,用setInterval解决。

但是此时我并不知道欠妥欠在什么地方,缺乏理论支持,现在闲下来仔细研究了一下

找问题

在仔细研究了旧版本后,我先把旧版本结构扒了出来,排除其他因素,自己模拟了一个简单版(就是上面的代码)

setTimeout:在执行时,是在载入后延迟指定时间后,去执行一次表达式,仅执行一次

setInterval:在执行时,它从载入后,每隔指定的时间就执行一次表达式

  • 实验一:在使用setInterval和setTimeout方法上,并没有什么问题,决定跑一下,结果如下

从结果得出两点结论

  1. setTimeout与setInterval并不是50倍速度配合运行着
  2. 两次interval间,timeout运行的次数越来越多,表明setInterval运行间隔越来越长,延迟越来越大
  • 实验二:加一点人工干预再执行
        function test() {
setInterval(function () {
console.log("interval");
play();
}, 2000);
}
function play() {
//延迟执行
for (var i = 0; i < 100000000; i++) { }
setTimeout(function () {
play();
console.log("setTimeout");
}, 40);
}

从结果得出两点结论

  1. setInterval可能会随函数处理时间,减少间隔
  2. 推测,因为Javascript是单线程的,setInterval和setTimeout是放队列里执行的,很容易受到回调事件影响
  • 实验三:拖动缩放浏览器

从结果得出结论

  1. 当浏览器标签切换到其他页面,或者浏览器最小化,会影响计时器,两者会出现间隔减小

涉及知识点

综上实验结果,网上搜集了一些资料能说明问题:

  1. JavaScript是单线程,但是浏览器是多线程,Javascript是浏览器多线程中的一个线程。(图参考自:https://www.cnblogs.com/tesky0125/p/4619549.html)

  1. Javascript会把执行的回调函数、浏览器的触发事件、UI渲染事件,先放到队列中,队列根据先进先出的规则,依次执行他们,当执行到队列中的setInterval时很难保证其与setTimeout同步关系还保持。
  2. setInterval无视代码错误:代码报错,但是setInterval依旧会按时执行,不会中断。
  3. setInterval无视网络延迟:如果调用ajax或其他服务,他不会管是否返回回调,会继续按时执行。
  4. setInterval不保证执行:因为setInterval会定时执行,如果函数逻辑很长,间隔时间内执行不完,后续方法会被抛弃。
  5. 会受浏览器状态影响,tab切换、最小化等

解决方案

在做轨迹播放时,setInterval的延迟还在可接受范围之内,但是网上给出的最佳解决方案是用setTimeout做。

setTimeout只会执行一次,在执行完成后,重新启动新的Timeout,时间runtime计算设置为差时,减少出现间隔越来越大的情况

        function test() {
//runTime,计算差时
runTime = 1000 - 执行耗时;
setTimeout(callback, runTime);
}
setTimeout(test, 1000);

JavaScript 关于setTimeout与setInterval的小研究的更多相关文章

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

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

  2. JavaScript的setTimeout和setInterval的深入理解

    发表过一片博客<跟着我用JavaScript写计时器>,比较基础.....有网友说应该写一下setTimeout的原理和机制,嗯,今天就来写一下吧: 直奔主题:setTimeout和set ...

  3. Javascript中setTimeout和setInterval的区别和使用

    在javascript中,window对象有两个主要的定时方法,分别是setTimeout 和 setInterval,其语法基本上相同,但是完成的功能取有区别. setTimeout方法是定时程序, ...

  4. JavaScript的setTimeout()和setInterval()

    1. setTimeout()方法 作用:在制定的毫秒数后调用函数或计算表达式 语法: setTimeout(code,millisec) 实例: function timedMsg() { var ...

  5. JavaScript中setTimeout()和setInterval()的区别

    含义: setTimeout()和setInterval()经常被用来处理延时和定时任务.使用setTimeout()处理延时任务,而使用setInterval()方法处理定时任务: setTimeo ...

  6. JavaScript———从setTimeout与setInterval到AJAX异步

    setTimeout与setInterval执行 首先我们看一下以下代码打印结果 console.log(1); setTimeout(function() { console.log(2); },1 ...

  7. javascript使用setTimeout、setInterval时找不到变量的问题

    我们在某个作用域内或者在自己定义的一个类里调用setTimeout.setInterval会经常会遇到找不到某个变量的错误. 比如下面这个例子: window.onload = function(){ ...

  8. javascript的setTimeout以及setInterval休眠问题。

    前端码农们在做项目中时候,必定不可少的需要做到轮播效果.但是有些特殊的需求,比如: 需要做到第一个容器内容轮播滚动之后,第二个容器内部再轮播滚动,再第三个容器内容轮播滚动. 这时候我的一开始的思路是: ...

  9. javascript定时器:setTimeout与setInterval

    概述: setTimeout:在指定的延迟时间之后调用一个函数或者执行一个代码片段,只执行一次: setInterval:周期性地调用一个函数(function)或者执行一段代码,重复执行: 语法格式 ...

随机推荐

  1. 百万年薪python之路 -- 并发编程之 多线程 一

    多线程 1.进程: 生产者消费者模型 一种编程思想,模型,设计模式,理论等等,都是交给你一种编程的方法,以后遇到类似的情况,套用即可 生产者与消费者模型的三要素: 生产者:产生数据的 消费者:接收数据 ...

  2. electron打包分发

    原始的方式打包 下载对应的版本号的Release Electron 然后把对应的项目方便整理成这样的目录结构(Windows下) node_modules重新安装,不然可能启动失败 把整文件夹给别人就 ...

  3. Mybatis常见配置错误总结

    Mybatis常见配置错误总结 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionF ...

  4. Java多线程编程(六)单例模式与多线程

    在使用多线程技术的单例模式时会出现一些意想不到的情况,这样的代码如果在生产环境中出现异常,有可能造成灾难性的后果. 一.立即加载/“饿汉模式” 立即加载就是使用类的时候已经将对象创建完毕,常见的实现方 ...

  5. 前端技术之:使用npx创建一个Nuxt.js项目

    $ npx create-nuxt-app my-first-nuxtjs npx: 401 安装成功,用时 43.891 秒 > Generating Nuxt.js project in / ...

  6. CVE-2019-13272 Linux kernel 权限许可和访问控制问题漏洞

    漏洞简介: Linuxkernel是美国Linux基金会发布的开源操作系统Linux所使用的内核. Linuxkernel5.1.17之前版本中存在安全漏洞,该漏洞源于kernel/ptrace.c文 ...

  7. 【XSY2488】【HDU5818】Joint Stacks

    这题合并栈让我们想到了左偏树. 我们可以维护val值为时间,dis值为size的左偏树,定义两个根root1和root2,表示两个栈的栈顶,建大根的左偏树. 接下来的插入,删除,两个栈合并都是左偏树的 ...

  8. iOS和macOS上的Message-ID和Mail.app深度链接

    如何在iOS上通过电子邮件进行无缝的“无密码”身份验证. Apple平台上的邮件和日历集成 在macOS和iOS上查看电子邮件时,邮件会在[检测到的日期和时间]下划线 .您可以与他们互动以创建新的日历 ...

  9. 建设城市(city):组合数,容斥原理

    想模一大堆人呢.考场上AC的大仙. 估计没人想给这题好好写一个题解吧,因为它的确挺简单的... 但是它对我来说一点都不简单啊!!! 至少出题人用脚写题解的时候肯定认为这道题是送分题了 容斥,枚举至少有 ...

  10. Vue躬行记(6)——内容分发

    Vue提供了一种内容分发技术,可将父组件中的内容传递给子组件的模板,实现方式参照了Web组件规范草案. 一.插槽 Vue内置了一个<slot>元素,能作为插槽(slot)存在,而插槽内可包 ...