这个问题也是在参加百度的前端技术学院中遇到的 任务中需要用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. OpenCascade Shape Representation in OpenSceneGraph

    OpenCascade Shape Representation in OpenSceneGraph eryar@163.com 摘要Abstract:本文通过程序实例,将OpenCascade中的拓 ...

  2. Spark入门实战系列--6.SparkSQL(下)--Spark实战应用

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .运行环境说明 1.1 硬软件环境 线程,主频2.2G,10G内存 l  虚拟软件:VMwa ...

  3. Azure ARM (4) 开始创建ARM Resource Group并创建存储账户

    <Windows Azure Platform 系列文章目录> 好了,接下来我们开始创建Azure Resource Group. 1.我们先登录Azure New Portal,地址是: ...

  4. C#实现WinForm窗体逐渐显示效果

    C#实现WinForm窗体逐渐显示效果,这个博客园里面已经有其它人已经实现了,原理很简单,就是通过定时改变窗体的透明度(从0到1,即透明度从完全透明到不透明),我这里也是按照这个思路来实现的,但是我做 ...

  5. jquery Ajax异步请求之session

    写了一个脚本,如下: $(function () { $("#btnVcode").click(function () { var receiveMobile = $(" ...

  6. C#身份证识别相关技术

    最近研究C#相关的OCR技术,图像识别一般C和C++这种底层语言做的比较多,C#主要是依托一些封装好的组件进行调用,这里介绍三种身份证识别的方法. 一:调用大公司API接口,百度.云脉,文通科技都有相 ...

  7. 【SQL】分配函数一枚[AllotToTable]

    适用环境:MSSQL 2005+.其中05需修改部分语句的写法才行,如: --变量的声明和赋值需分开写 --需改为如下 --05不支持+=这样的复合运算符 --需改为如下 功能: 将一个数字(整数或有 ...

  8. [前端]使用JQuery UI Layout Plug-in布局 - wolfy

    引言 使用JQuery UI Layout Plug-in布局框架实现快速布局,用起来还是挺方便的,稍微研究了一下,就能上手,关于该布局框架的材料,网上也挺多的.在项目中也使用到了,不过那是前端的工作 ...

  9. 编写高性能SQL

    前言:系统优化中一个很重要的方面就是SQL语句的优化.对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可达到上百倍,可见对于一个系统不是简单的能实现其功能就可以了,而是要写出高质量的SQL语 ...

  10. 孙鑫MFC学习笔记5:文本显示

    1.CreateSolidCaret添加一个插入符 参数:宽度,高度 如果设为0,就设为默认窗口边界的宽度和高度 2.GetSystemMetrics获取默认窗口边界的宽度和高度 3.Caret在创建 ...