setInterval和setTimeout
setTimeout和setInterval的基本用法我们不谈,无非是1.指定延迟后调用函数,2.以指定周期调用函数
让我们想象一个意外情况,比如说下面的setInterval
setInterval(function(){ func(i++);},100) |
我们以每100毫秒调用一次func函数,如果func的执行时间少于100毫秒的话好办,在遇到下一个100毫秒前就能够执行完:

但如果func的执行时间大于100毫秒,该触发下一个func函数时之前的还没有执行完怎么办?(前提是你要知道javascript只有单线程,不存在同时执行致命一说,才会有这个问题)。答案如下图所示,那么第二个func会在队列(这里的队列是指event loop,在下文中会详细提到)中等待,直到第一个函数执行完

如果第一个函数的执行时间特别长,在执行的过程中本应触发了许多个func怎么办,那么所有这些应该触发的函数都会进入队列吗?
不,只要发现队列中有一个被执行的函数存在,那么其他的统统忽略。如下图,在第300毫秒和400毫秒处的回调都被抛弃,一旦第一个函数执行完后,接着执行队列中的第二个,即使这个函数已经“过时”很久了。

还有一点,虽然你在setInterval的里指定的周期是100毫秒,但它并不能保证两个函数之间调用的间隔一定是一百毫秒。在上面的情况中,如果队列中的第二个函数时在第450毫秒处结束的话,在第500毫秒时,它会继续执行下一轮func,也就是说这之间的间隔只有50毫秒,而非周期100毫秒
那如果我想保证每次执行的间隔应该怎么办?用setTimeout,比如下面的代码:
var i =1 var timer = setTimeout(function(){ alert(i++) timer = setTimeout(arguments.callee,2000)},2000) |
setInterval的问题:
1. 某些间隔会被跳过
2.多个定时器的代码执行之间的间隔可能比预期要小
所以常用setTimeout代替setInterval
setInterval(fn,time)
//↓↓↓↓↓↓↓↓↓↓↓↓
setTimeout(function(){
fn();
setTimeout(arguments.callee,time);
},time);
这样每次函数执行的时候都会创建一个新的定时器,第二个setTimeout()调用使用了agrument.callee 来获取当前实行函数的引用,并设置另外一个新定时器。这样做可以保证在代码执行完成前不会有新的定时器插入,并且下一次定时器代码执行之前至少要间隔指定时间,避免连续运行。
setInterval 的堆调用
setTimeout 只会执行回调函数一次,不过 setInterval - 正如名字建议的 - 会每隔 X 毫秒执行函数一次。 但是却不鼓励使用这个函数。
当回调函数的执行被阻塞时,setInterval 仍然会发布更多的回调指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。
function foo(){
// 阻塞执行 1 秒
}
setInterval(foo, 100);
上面代码中,foo 会执行一次随后被阻塞了一秒钟。
在 foo 被阻塞的时候,setInterval 仍然在组织将来对回调函数的调用。 因此,当第一次 foo 函数调用结束时,已经有 10 次函数调用在等待执行。
处理可能的阻塞调用
最简单也是最容易控制的方案,是在回调函数内部使用 setTimeout 函数。
function foo(){
// 阻塞执行 1 秒
setTimeout(foo, 100);
}
foo();
这样不仅封装了 setTimeout 回调函数,而且阻止了调用指令的堆积,可以有更多的控制。 foo 函数现在可以控制是否继续执行还是终止执行。
手工清空定时器
可以通过将定时时产生的 ID 标识传递给 clearTimeout 或者 clearInterval函数来清除定时, 至于使用哪个函数取决于调用的时候使用的是 setTimeout还是 setInterval。
var id = setTimeout(foo, 1000);
clearTimeout(id);
隐藏使用 eval
setTimeout 和 setInterval 也接受第一个参数为字符串的情况。 这个特性绝对不要使用,因为它在内部使用了 eval。
注意: 由于定时器函数不是 ECMAScript 的标准,如何解析字符串参数在不同的 JavaScript 引擎实现中可能不同。 事实上,微软的 JScript 会使用 Function 构造函数来代替 eval 的使用。
function foo() {
// 将会被调用,输出2
console.log(2);
}
function bar() {
function foo() {
// 不会被调用,不输出22
console.log(22);
}
setTimeout('foo()', 1000);
}
bar();
由于 eval 在这种情况下不是被直接调用,因此传递到 setTimeout 的字符串会自全局作用域中执行; 因此,上面的回调函数使用的不是定义在 bar 作用域中的局部变量 foo。
setInterval和setTimeout的更多相关文章
- JavaScript DOM 编程艺术·setInterval与setTimeout的动画实现解析
先贴上moveElement()函数的大纲,为了方便观看,删了部分代码,完整版粘到文章后面. function moveElement(elementID,final_x,final_y,interv ...
- JavaScript SetInterval与setTimeout使用方法详解
setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码.不过这两个函数还是有区别的 ...
- JS里设定延时:js中SetInterval与setTimeout用法
js中SetInterval与setTimeout用法 JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延迟一段时间,再进行某项操 ...
- 关于setInterval和setTImeout中的this指向问题
前些天在练习写一个小例子的时候用到了定时器,发现在setInterval和setTimeout中传入函数时,函数中的this会指向window对象,如下例: var num = 0; function ...
- js-定时任务setInterval,setTimeout,clearInterval,clearTimeout
setInterval()循环执行相应的方法 <script type="text/javascript"> setInterval("myInterval( ...
- Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)
最近在做项目时用到了定时执行的js方法,setInterval与setTimeout时间长了不用有些生疏了,所以自己总结了一下,记下来,以便以后使用. Document自带的方法: 循环执行:var ...
- webapp 慎用setInterval、setTimeout
其实这片文章刚开始我啥也没写的,但也有20多的访问量,所以觉得大家还是比较关注这个问题,所以找机会写下. 问题的引出: 为什么我说的时webapp中慎用setInterval.setTimeout, ...
- js学习--浏览器对象计时器setInterval()与setTimeout()的使用与区别
一.setInterval()与setTimeout()的定义: 二.setInterval()与setTimeout()的使用: 1.setInterval()与clearInterval() ...
- js定时器setInterval()与setTimeout()
js定时器setInterval()与setTimeout() 1.setTimeout(Expression,DelayTime),在DelayTime过后,将执行一次Expression,setT ...
- setInterval 和 setTimeout
setInterval 和 settimeout的区别 setinterval 1.会造成某些间隔会被跳过2.多个定时器之间的执行代码事假间隔比预期的小 而且 当定时器代码添加到任务队列里面没有被执行 ...
随机推荐
- 手机升级到iOS10,用Xcode7.3进行真机调试方法
今天发布的正式版的iOS10,手机果断升级了,结果发现Xcode7.3不能真机调试了,原因是Xcode7.3里面没有iOS10的sdk,下面这个压缩包你可以下载下来放在你的Xcode7.3里面,当然了 ...
- IOS Core Animation Advanced Techniques的学习笔记(一)
转载. Book Description Publication Date: August 12, 2013 Core Animation is the technology underlying A ...
- ssh 整合
1. 加入 Spring 1). 加入 jar 包 2). 配置 web.xml 文件 3). 加入 Spring 的配置文件. 2. 加入 Hibernate 1). 同时建立持久化类, 和其对应的 ...
- IOS 学习 开发 自定义 UINavigationController 导航
文件目录如下:基本导航顺序: root -> First -> Second -> Third.其中,FirstViewController作为 navigation堆栈的rootv ...
- 解决远程连接mysql错误1130代码的方法
命令行登陆 mysql -uroot -p 输入密码后登陆 use mysql; select host,user from user ; grant allon *.*to root i ...
- IIC总线解析
IIC简介: IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控 ...
- 阿里云服务器被挖矿minerd入侵的解决办法
上周末,更新易云盘的时候,发现阿里云服务器CPU很高,执行 top 一看,有个进程minerd尽然占用了90%多的CPU, 赶紧百度一下,查到几篇文章都有人遇到同样问题 Hu_Wen遇到的和我最相似, ...
- java开发连接Oracle 12c采用PDB遇到问题记录
今天初次使用java连接Oracle 12c,遇到各种问题,为方便后续查询,在汇总了问题记录及解决方案如下. ORA-28040: No matching authentication protoco ...
- .NET C# 将 mdb 中数据读为 list<string[]> 其中 path 为数据库地址 ,sql 为查询语句
using System.Data; using System.Data.OleDb; public static List<string[]> select_list(string pa ...
- Android ShapeDrawable
今天做项目碰到一个这样的情况,就是颜色指示框,用的是正方形边框是黑色的,里面填充颜色,颜色值是动态的,为了解决这个问题,查了好多资料,终于找到解决的方法,利用ShapeDrawable,我们自定义一个 ...