这个问题也是在参加百度的前端技术学院中遇到的 任务中需要用js实现动画  导师给的评价中setInterval会导致bug 当时不理解   下面把自己学习的过程分享出来

再次理解单线程

  老是说js是单线程的,其实自己根本没有好好的理解好这个单线程的意思,就比如我对这个setTimeout(function(){},time)的理解就是在从现在开始到time时间点就会执行的一段代码,其实这样的理解是有问题的,定时器只是计划代码在未来的某个时间执行,但是这个时机是无法保证的 ,这句话能更好的帮助我们理解好js的单线程(是不是可以这样理解 就是各个代码对js单线程的争夺占用

其实可以把js想象是在一个时间线上运行的,我们添加的事件处理函数和ajax回调都是在这个时间线上添加一定的代码,等待执行,当前一段代码执行过后,这个时间线就处于空闲状态,就会执行后续的代码,(在JavaScript中,没有任何代码是立刻执行的,但一旦进程空闲则尽快执行)也就出现了这样的场景就是

    var btn = document.getElementById("btn");
    btn.addEventListener("click",function(){
      setTimeout(function(){
          console.log(1);
      },1000);
      /*事件处理程序的其他逻辑*/
    },false);

这个例子能充分的反映出我之前的错误理解,上面的例子当响应点击事件,在1000ms后将一段代码加入了js执行的时间线上(队列),按我之前的理解就是1000ms后console.log(1)就会执行,但是上面的例子中事件处理程序的其他逻辑的执行时间超出了1000ms,setTimeout就不是在设置完1000ms之后执行了,因为需要等待时间线(队列)的空闲,通过上面的例子我们就很好的理解了setTimeout

2016.6.10 定时器执行的代码只有在创建它的函数执行完之后才可能被执行

setInterval

通过对setTimeout的理解,发现之前对setInterval的理解也存在问题,setInteral(function(){},time) 我的理解是间隔一定的时间段就会去执行的代码,但是这些代码之间会相互干扰吗,他们之间的切换呢 ,这些问题我都没考虑过,setInterval会导致bug我也是一头雾水

首先setInterval的功能的确是每隔一定的时间间隔在时间线(队列)中插入代码,并且js的引擎提供了这样的机制,就是当这个代码的实例已经存在这个时间线(队列)中,不会将这段代码继续的添加到时间线(队列),这样就能保证定时器的代码加入到队列中的最小时间间隔是指定的间隔,但是这种方式有一定的问题,也就是会出现bug

(1)某些间隔会被跳过

(2)多个定时器的代码执行之前的间隔可能会比预期的小

理解定时器代码实例

  定时器代码的实例指的是指的是被添加到事件处理时间线(队列)中的定时器代码 于是出现了这样的场景,我们每隔200ms设置一个定时器去执行, 于是就有了下面的场景

    var btn = document.getElementById("btn");
    btn.addEventListener("click",function(){
      setInterval(function(){
          console.log(1);
      },1000);
      /*事件处理程序的其他逻辑*/
    },false);

上面的例子中当相应btn的click事件处理程序后每隔一定的时间间隔就是在事件处理的时间线(队列)中添加一定的等待执行的代码,加入添加了第一段定时器代码后,事件处理程序仍然在运行,这个事件处理程序运行完毕后,会将js单线程的控制权交给第一段定时器代码,这个时候运行第一段定时器代码,此时由于时间线中不存在定时器代码的实例,允许添加第二段定时器代码,加入添加完第二段代码后,第一段定时器的代码仍然在运行,当需要添加第三段定时器代码的时候,由于时间线和队列中存在定时器代码的实例(也就是第二段定时器代码),这个时候就会出现这个场景第一段定时器代码执行完毕后,由于时间线中只存在第二段定时器代码,它会被立刻执行,而且上面的情况跳过了第三段定时器代码

为了避免setInterval的重复定时器的缺点,可以使用链式调用的setTimeout() 模式

  setTimeout(function(){
    setTimeout(arguments.callee,interval);
  },interval);

优点:(1)它能保证在函数执行的过程中,在前一个定时器代码执行完毕之前,不会向时间线和队列中插入新的代码,确保不会有任何的缺失的时间间隔

(2)能保证在下一个定时器执行之前,至少等待了指定的时间间隔,避免了连续的运行

   setTimeout(function(){
     var div = document.getElementById("myDiv");
     var left = parseInt(div.style.left) + 5;
     div.style.left = left + "px";
     if(left <= 200) {
       setTimeout(arguments.callee,50);
     }

   },50);

动画的更好的实现方式  requestAnimationFrame 当我们使用setTimeout或者setInterval的时候,会有动画过度绘制,浪费 CPU 周期以及消耗额外的电能等问题,requestAnimationFrame会解决关键帧丢失的问题,并且它会把每一帧中所有的DOM操作集合起来在一次重绘中完成,并且这个重绘的时间间隔是根据浏览器的刷新频率的并且它不会对隐藏或者不可见的频率进行重绘,也就减少了CPU和内存的使用

  var demo = document.getElementById("myDiv");
  function render() {
    demo.style.left = parseInt(demo.style.left) + 5 + "px";
  }
  requestAnimationFrame(function(){
    render();
    if(parseInt(demo.style.left) <= 300) {
      requestAnimationFrame(arguments.callee);
    }
  });

我对比了setTimeout和requestAnimationFrame 这两种模式  发现 requestAnimationFrame这种的确更流畅

参考 JavaScript高级程序设计

性能更好的js动画实现方法--requestAnimationFrame

2016 7 24   Raf 相关学习

javascript高性能动画与页面渲染

2016 9 28  函数节流  之前讨论的问题的每个一定的时间间隔去执行一定的代码  函数节流是某段代码不可以在没有间断的情况下连续的执行 这个方式可以用在一些不能频繁操作的地方 例如会造成大量DOM操作的事件上 (输入联想等 )

思路  第一次调用函数的时候,创建一个定时器 在指定的时间间隔之后运行代码 当第二次调用该函数的时候 它会清除之前的定时器 如果之前的定时器已经执行过了,就相当于新加入一个定时器 否则就是取消了之前的操作 新加入定时器 就能避免短时间的频繁的操作

模式

function throttle(method,context) {
          clearTimeout(emthod.tId);
          method.tId = setTimeout(function(){
            method.call(context)
          },1000);
        }

定时器相关 setTimeout setInterval 函数节流的更多相关文章

  1. 定时器setTimeout实现函数节流

    问题描述 文字输入查询的keyup或oninput事件,实现实时查询功能. 在用户输入过程中,用户可能只想需要 '小' 字的查询结果,但是以上两个事件会触发'x'.'i'.'a'.'o'.'小',一共 ...

  2. js 定时器(setTimeout/setInterval)出现变量未定义(xxx is not defined) 的解决方法

    首先声明本人资质尚浅,如有错误,欢迎指正.共同提高. ------------------------------------------------------------------------- ...

  3. javascript 定时器 timer setTimeout setInterval (js for循环如何等待几秒再循环)

    实现一个打点计时器,要求1.从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 12.返回的对象中需要包含一个 cance ...

  4. 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply

    一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...

  5. js中setTimeout/setInterval定时器用法示例

    js中setTimeout(定时执行一次)和setInterval(间隔循环执行)用法介绍. setTimeout:在指定的毫秒数后调用指定的代码段或函数:setTimeout示例代码 functio ...

  6. javascript 函数返回值(return)、定时器(setTimeout、setInterval)

    一.函数的返回值:return 1.函数名+括号=return后面的值 <script> function fn1(){ return 100; } alert(fn1()); // 10 ...

  7. 关于setTimeout的妙用前端函数节流

    最近在某团队忙于一个项目,有这么一个页面,采用传统模式开发(吐槽它为什么不用React),它的DOM操作比较多,然后性能是比较差的,尤其当你缩放窗口时,可怕的事情发生了,出现了卡顿,甚至浏览器瘫痪.为 ...

  8. 什么是setTimeout函数和setInterval函数?

    我们一般在浏览网页的时候,一般都会有图片轮播等,一些比较好玩的特效,接下来我就给大家讲讲这俩个函数! 一setTimeout函数和setInterval函数的语法以及应用 1.setTimeout函数 ...

  9. Javascript定时器(二)——setTimeout与setInterval

    一.解释说明 1.概述 setTimeout:在指定的延迟时间之后调用一个函数或者执行一个代码片段 setInterval:周期性地调用一个函数(function)或者执行一段代码. 2.语法 set ...

随机推荐

  1. poj1062昂贵的聘礼(Dijkstra**)

    /* 题意: 物主有一个物品,价值为P,地位为L, 以及一系列的替代品Ti和该替代品所对应的"优惠"Vi g[u][i] 表示的是u物品被i物品替换后的优惠价格!(u>0, ...

  2. 关于orapwd命令entries参数的探究

    今日早上看Oracle官方文档<Administrator's Guide>时,在密码文件章节,关于orapwd命令entries参数的说明如下: This argument specif ...

  3. Oracle Dataguard之failover

    Oracle Dataguard中,角色转换包含两类:Switchover和Failover.上文<Oracle Dataguard之switchover>中,我们已经谈过了switcho ...

  4. 转载----How fast is Redis?

    How fast is Redis? Redis includes the redis-benchmark utility that simulates running commands done b ...

  5. 动态单链表的传统存储方式和10种常见操作-C语言实现

    顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...

  6. Nutch源码阅读进程5---updatedb

    看nutch的源码仿佛就是一场谍战片,而构成这精彩绝伦的谍战剧情的就是nutch的每一个从inject->generate->fetch->parse->update的环节,首 ...

  7. 碉堡了! 纯 CSS 绘制《辛普森一家》人物头像

    这篇文章给大家分享一组纯 CSS 绘制的<辛普森一家>人物头像.<辛普森一家>(The Simpsons)是马特·格勒宁为美国福克斯广播公司创作的一部动画情景喜剧.该剧通过对霍 ...

  8. MyBaits学习

    一:配置MyBaits的开发环境 1.1.核心配置文件 正如hibernate一样,MyBaits也有一个核心的配置文件,它包含着数据源地址,用户名,密码等,还有着各个实体类的配置文件,配置文件是xm ...

  9. 解决The file “FWLifeApp” couldn’t be opened because you don’t have permission to view it.问题

    The file “FWLifeApp” couldn’t be opened because you don’t have permission to view it问题是因为项目文件中的Bundl ...

  10. 【Swift学习】Swift编程之旅(一)

    学习一门新语言最经典的例子就是输出“Hello World!” print("Hello World!") swift就是这样来输出的. 如果你使用过其他语言,那么看上去是非常的熟 ...