定时器相关 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 ...
随机推荐
- js提取正则中的字符串
代码如下: var results = data.match(/(start=').*?(')/); if (results != null) { console.log(data[0]); }
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- php基础教程-必备基础知识
PHP 脚本在服务器上执行. 您应当具备的基础知识 在继续学习之前,您需要对下面的知识有基本的了解: HTML CSS JavaScript 如果您希望首先学习这些项目,请在我们的 首页 访问这些教程 ...
- office2010里怎么设置页码为第几页共几页
在office2010里设置页眉,页脚,页码是很方便的,页眉页脚可以方便的添加信息,统一文本格式,页码的添加可以让读者清楚的知道阅读的进度,也可以方便下次阅读时从相应的页码开始阅读,就像软件中的进度条 ...
- Windows Azure Cloud Service (1) 用户手册
<Windows Azure Platform 系列文章目录> 下载地址 Cloud Service用户手册
- Git:错误:error:src refspec master does not match any
新建立了一个远程仓库,想着把项目放上去.于是在项目目录上: git init 然后就添加远程库 git remote add origin xxxx.git 然后就想push: git push -u ...
- PHP 中的Closure
PHP 中的Closure Closure,匿名函数,又称为Anonymous functions,是php5.3的时候引入的.匿名函数就是没有定义名字的函数.这点牢牢记住就能理解匿名函数的定义了. ...
- php的memcache和memcached扩展区别
老生长谈的问题了.我这里就整理一下. memcache的文档在:http://pecl.php.net/package/memcache memcached的文档在:http://pecl.php.n ...
- IIS各个版本中你需要知道的那些事儿
一.写在前面 目前市面上所用的IIS版本估计都是>=6.0的.所以我们主要以下面三个版本进行讲解 服务器版本 IIS默认版本 server2003 6.0 server2008 7.0 serv ...
- OpenStack虚拟云桌面在携程呼叫中心的应用
编者:本文为刘科在第六期[携程技术微分享]中的分享内容.在携程技术中心(微信号ctriptech)微信后台回复[云桌面],可加入微信交流群,和关注云桌面的小伙伴一起玩耍~ 刘科,携程系统研发云平台桌面 ...