定时器相关 setTimeout setInterval 函数节流
这个问题也是在参加百度的前端技术学院中遇到的 任务中需要用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 相关学习
2016 9 28 函数节流 之前讨论的问题的每个一定的时间间隔去执行一定的代码 函数节流是某段代码不可以在没有间断的情况下连续的执行 这个方式可以用在一些不能频繁操作的地方 例如会造成大量DOM操作的事件上 (输入联想等 )
思路 第一次调用函数的时候,创建一个定时器 在指定的时间间隔之后运行代码 当第二次调用该函数的时候 它会清除之前的定时器 如果之前的定时器已经执行过了,就相当于新加入一个定时器 否则就是取消了之前的操作 新加入定时器 就能避免短时间的频繁的操作
模式
function throttle(method,context) { clearTimeout(emthod.tId); method.tId = setTimeout(function(){ method.call(context) },1000); }
定时器相关 setTimeout setInterval 函数节流的更多相关文章
- 定时器setTimeout实现函数节流
问题描述 文字输入查询的keyup或oninput事件,实现实时查询功能. 在用户输入过程中,用户可能只想需要 '小' 字的查询结果,但是以上两个事件会触发'x'.'i'.'a'.'o'.'小',一共 ...
- js 定时器(setTimeout/setInterval)出现变量未定义(xxx is not defined) 的解决方法
首先声明本人资质尚浅,如有错误,欢迎指正.共同提高. ------------------------------------------------------------------------- ...
- javascript 定时器 timer setTimeout setInterval (js for循环如何等待几秒再循环)
实现一个打点计时器,要求1.从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 12.返回的对象中需要包含一个 cance ...
- 前端笔记之JavaScript(九)定时器&JSON&同步异步/回调函数&函数节流&call/apply
一.快捷位置和尺寸属性 DOM已经提供给我们计算后的样式,但是还是觉得不方便,因为计算后的样式属性值都是字符串类型. 不能直接参与运算. 所以DOM又提供了一些API:得到的就是number类型的数据 ...
- js中setTimeout/setInterval定时器用法示例
js中setTimeout(定时执行一次)和setInterval(间隔循环执行)用法介绍. setTimeout:在指定的毫秒数后调用指定的代码段或函数:setTimeout示例代码 functio ...
- javascript 函数返回值(return)、定时器(setTimeout、setInterval)
一.函数的返回值:return 1.函数名+括号=return后面的值 <script> function fn1(){ return 100; } alert(fn1()); // 10 ...
- 关于setTimeout的妙用前端函数节流
最近在某团队忙于一个项目,有这么一个页面,采用传统模式开发(吐槽它为什么不用React),它的DOM操作比较多,然后性能是比较差的,尤其当你缩放窗口时,可怕的事情发生了,出现了卡顿,甚至浏览器瘫痪.为 ...
- 什么是setTimeout函数和setInterval函数?
我们一般在浏览网页的时候,一般都会有图片轮播等,一些比较好玩的特效,接下来我就给大家讲讲这俩个函数! 一setTimeout函数和setInterval函数的语法以及应用 1.setTimeout函数 ...
- Javascript定时器(二)——setTimeout与setInterval
一.解释说明 1.概述 setTimeout:在指定的延迟时间之后调用一个函数或者执行一个代码片段 setInterval:周期性地调用一个函数(function)或者执行一段代码. 2.语法 set ...
随机推荐
- android api sdk
Platform Version API Level VERSION_CODE Notes Android 6.0 23 M API Changes Android 5.1 22 LOLLIPOP_M ...
- ZZUOJ1196: 单调数
/* 注意的事项:是输出小于 10^n的正整数的个数哦!开始的时候总比样例输出多一个数, 纠结了好久,原来是 0加了进去了! dpI[n][m]表示的是第n位添加数字m(0....9)的构成单调递增数 ...
- 【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 Matlab和C#混合编程文章目录 :[目录]Matlab和C#混合编程文章目录 在我的上一篇文章[ ...
- mysql replication principle--转
原文地址:http://www.codeweblog.com/mysql-replication-principle/ 1, the replication process Mysql replica ...
- 学习使用 CSS3 制作网站面包屑导航效果
作为最重要的导航展示形式之一,面包屑导航能够让用户更清楚的知道他们所在页面的层次结构,让他们可以方便的导航到上一层页面.在本教程中,您将学习如何使用 CSS3 技术创建自己的面包屑导航效果. 效果演示 ...
- emacs: 文本输入中文件目录自动补全
emacs: 文本输入中文件目录自动补全 // */ // ]]> UP | HOME emacs: 文本输入中文件目录自动补全 Table of Contents 1 引言 2 补全过程演 ...
- Azure China (3) 使用Visual Studio 2013证书发布Cloud Service至Azure China
<Windows Azure Platform 系列文章目录> 之前有很多网友询问我如何通过VS发布Cloud Service至Azure China,这里我专门写篇文章,给大家详细介绍下 ...
- Windows Azure Web Site (15) 取消Azure Web Site默认的IIS ARR
<Windows Azure Platform 系列文章目录> 我们知道,Azure Web Site (改名为Azure Web App)默认是可以保留Session的.Azure We ...
- JAVA 设计模式 解释器模式
用途 解释器模式 (Interpreter) 定义一个语言,定义它的文法的一种表示. 并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 解释器模式是一种行为型模式. 结构
- 实现iOS图片等资源文件的热更新化(零): 序
必要的序 以后在写系列文章,准备把基本的规划和动机等,单独作为一个小的序言部分给独立出来.序言部分,可以较为完整地交待系列文章的写作动机,所展示的编码技术可能的应用场景等.个人,我还是比较看重文章或者 ...