这个问题也是在参加百度的前端技术学院中遇到的 任务中需要用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. Android项目中,在一个数据库里建立多张表

    一,创建一个公共的DBAdapter; 为了在整个程序运行期间调用该公共的数据库,我们定义了一个扩展自Application的CommDB类: 1,创建唯一的数据库: public class Com ...

  2. 深入理解CSS溢出overflow

    × 目录 [1]定义 [2]属性 [3]失效[4]应用 前面的话 当一个元素固定为某个特定大小,但内容在元素中放不下.此时就可以利用overflow属性来控制这种情况 定义 overflow溢出 值: ...

  3. Docker之Linux UnionFS

    UnionFS UnionFS是一种为Linux,FreeBSD和NetBSD操作系统设计的把其他文件系统联合到一个联合挂载点的文件系统服务.它使用branch把不同文件系统的文件和目录"透 ...

  4. 高拍仪拍照SDK开发(良田影像S300L|S500L)

    高拍仪拍照SDK开发下载地址:点击下载 本SDK适用于:良田影像S300L|S500L 高拍仪如图: SDN开发包安装之后找到安装目录,如图: 大家找到各自需要的版本即可,需要注意的是如果需要上传图片 ...

  5. Hadoop官方文档翻译——MapReduce Tutorial

    MapReduce Tutorial(个人指导) Purpose(目的) Prerequisites(必备条件) Overview(综述) Inputs and Outputs(输入输出) MapRe ...

  6. 加速Web开发的9款知名HTML5框架

    与手工编码比起来,HTML5框架在准确性和正确率方面给予了保证.大多数HTML5框架都会有一个组合或者包含一些额外的组件,比如jQuery Scripts.CSS3样式表则以改善多媒体特征的功能性和响 ...

  7. ASP.NET 文件下载

    using System; using System.Web; using System.IO; public partial class _Default : System.Web.UI.Page ...

  8. WCF服务创建与使用(双工模式)

    昨天发布了<WCF服务创建与使用(请求应答模式)>,今天继续学习与强化在双工模式下WCF服务创建与使用,步骤与代码如下. 第一步,定义服务契约(Service Contract),注意Se ...

  9. 细说ASP.NET Core与OWIN的关系

    前言 最近这段时间除了工作,所有的时间都是在移植我以前实现的一个Owin框架,相当移植到到Core的话肯定会有很多坑,这个大家都懂,以后几篇文章可能会围绕这个说下,暂时就叫<Dotnet Cor ...

  10. 最简单的pagging插件

    <html> <head> <title>jQuery Easy-Paging Test</title> </head> <body& ...