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的更多相关文章

  1. JavaScript DOM 编程艺术·setInterval与setTimeout的动画实现解析

    先贴上moveElement()函数的大纲,为了方便观看,删了部分代码,完整版粘到文章后面. function moveElement(elementID,final_x,final_y,interv ...

  2. JavaScript SetInterval与setTimeout使用方法详解

    setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码.不过这两个函数还是有区别的 ...

  3. JS里设定延时:js中SetInterval与setTimeout用法

     js中SetInterval与setTimeout用法 JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延迟一段时间,再进行某项操 ...

  4. 关于setInterval和setTImeout中的this指向问题

    前些天在练习写一个小例子的时候用到了定时器,发现在setInterval和setTimeout中传入函数时,函数中的this会指向window对象,如下例: var num = 0; function ...

  5. js-定时任务setInterval,setTimeout,clearInterval,clearTimeout

    setInterval()循环执行相应的方法 <script type="text/javascript"> setInterval("myInterval( ...

  6. Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)

    最近在做项目时用到了定时执行的js方法,setInterval与setTimeout时间长了不用有些生疏了,所以自己总结了一下,记下来,以便以后使用. Document自带的方法: 循环执行:var ...

  7. webapp 慎用setInterval、setTimeout

    其实这片文章刚开始我啥也没写的,但也有20多的访问量,所以觉得大家还是比较关注这个问题,所以找机会写下. 问题的引出: 为什么我说的时webapp中慎用setInterval.setTimeout, ...

  8. js学习--浏览器对象计时器setInterval()与setTimeout()的使用与区别

    一.setInterval()与setTimeout()的定义: 二.setInterval()与setTimeout()的使用:    1.setInterval()与clearInterval() ...

  9. js定时器setInterval()与setTimeout()

    js定时器setInterval()与setTimeout() 1.setTimeout(Expression,DelayTime),在DelayTime过后,将执行一次Expression,setT ...

  10. setInterval 和 setTimeout

    setInterval 和 settimeout的区别 setinterval 1.会造成某些间隔会被跳过2.多个定时器之间的执行代码事假间隔比预期的小 而且 当定时器代码添加到任务队列里面没有被执行 ...

随机推荐

  1. css 分享之background-attachment 属性

    微分享才发现的css背景图达到的效果代码属性: background-attachment -- 定义背景图片随滚动轴的移动方式: 值 描述 scroll 默认值.背景图像会随着页面其余部分的滚动而移 ...

  2. MD5加密、时间戳转换、base64算法加密、解密

    #region MD5加密 /// <summary> /// MD5加密 /// </summary> /// <param name="str"& ...

  3. daydayup1 codeforces141c

    题意:给定n个数字,代表每个人前面有几个人比他高,让你构造一个height数组,满足条件 思路:直接贪心就好,假设到第i个人,设他的高度为i-a[i]+1,前面比他高的人每个人的高度加1

  4. C++ 类、构造析构、深拷贝

    1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作.以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时 ...

  5. sh back mongo

    !/bin/shBACK_DB=ALLOUT_DIR=/home/jianyeruan/app/mongo #临时备份目录TAR_DIR=/home/jianyeruan/app/mongotar # ...

  6. SpringMVC RequestMapping & 请求参数

    SpringMVC 概述 Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一 Spring3.0 后全面超越 Struts2,成为最优秀的 MVC ...

  7. spring事务详解(转载+高亮)

    spring提供的事务管理可以分为两类:编程式的和声明式的.编程式的,比较灵活,但是代码量大,存在重复的代码比较多:声明式的比编程式的更灵活.编程式主要使用transactionTemplate.省略 ...

  8. [SCOI2007] 修车

    属于我的费用流版本终于诞生了!想来还有点小激动呢…看了下模板,之后完全按照自己的想象来写,这样在考场上也不怕啦~ 某人说其实费用流就是把Dinic里的BFS换成SPFA,似乎还是比较有道理的,就是ad ...

  9. android退出MainActivity后onDestroy不回调

    问题:有时点击back键,退出MainActivity后,app已不可见,但是onDestroy却没有被调用. 原因: 1. onBackPressed被覆盖 @Override public voi ...

  10. ie8 window.open导出文件报错

    js创建一个<a>元素hiddenElementhiddenElement.setAttribute('href','')hiddenElement.setAttribute('targe ...