深入浅出理解JavaScript高级定时器原理与用法

本文实例讲述了JavaScript高级定时器原理与用法。分享给大家供大家参考,具体如下:

setTimeout()setInterval()可以用来创建定时器,其基本的用法这里就不再做介绍了。这里主要介绍一下javascript的代码队列。在javascript中没有任何代码是立即执行的,一旦进程空闲则尽快执行。所以说定时器中设置的时间并不代表执行时间就一定相符,而是代表代码会在指定时间间隔后加入到队列中进行等待。如果在这个时间点上,队列中没有其他东西,那么这段代码就会被执行,表面上看上去好像代码就在精确指定的时间点上执行了。所以就会产生一些问题。

重复定时器

通常,我们使用setInterval方法来以相同时间间隔重复执行某段代码。但是使用该方法会有两个问题:第一个就是某些间隔会被跳过;第二个就是多个定时器的代码执行之间的间隔可能会比预期的小。

在这里,我们来举个例子:如果某个onclick事件处理程序使用setInterval设置了一个200ms间隔的重复定时器,如果事件处理程序花了300ms的时间完成,就会跳过一个时间间隔同时运行着一个定时器代码。

我们也可以通过下面的代码来得到结论:

//重复定时器
var i =0;
setInterval(function(){
 //如果事件处理时间长于间隔时间
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
},100);
//可以明显感觉到时间间隔不相等

为了避免这种时间间隔的问题,我们可以采用链式调用setTimeout方法来取代setInterval

//可以采用链式调用setTimeout来取代setInterval
var i = 0;
setTimeout(function(){
 //处理内容
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
 //
 setTimeout(arguments.callee,100);
},100);
//这样处理效果明显好多了。

每次函数执行的时候都会创建一个新的定时器,第二个setTimeout调用使用了arguments.callee来获取对当前执行的函数的引用,并为其设置另外一个定时器。这样做是为了在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔,也保证了在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行。可谓一举两得,现在主流框架中的动画一般都是这样来实现重复定时的。

函数节流

定时器不仅仅是用来定时的,也可以用来缓解浏览器的压力。浏览器中某些计算和处理要比其他的昂贵很多,比如说DOM操作,就会需要更多的内存和CPU时间,连续使用过多的DOM操作可能会导致浏览器挂起,甚至崩溃。

函数节流的基本思想就是,某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置一个。目的就是为了在执行函数的请求停止一段时间后再执行。

代码如下:

//再来谈谈函数节流
function throttle(method,context){
 clearTimeout(method.tId);
 method.tId = setTimeout(function(){
 method.call(context);
 },100);
}
//该函数接受两个参数,第一个是要执行的函数,第二个是作用域。
//使用方法demo
//未使用情况:
window.onresize = function(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
//使用情况;
function resizeDiv(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
window.onresize = function(){
 throttle(resizeDiv);
};
//只要代码是周期性执行的,都应该使用节流。

这样给用户的感觉并不会很大,确是给浏览器减少了不少的压力。函数节流也是很多框架常用的技巧之一。

demo示例:

//重复定时器
/*var i =0;
setInterval(function(){
 //如果事件处理时间长于间隔时间
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
},100);*/
//可以明显感觉到时间间隔不相等
//可以采用链式调用setTimeout来取代setInterval
/*var i = 0;
setTimeout(function(){
 //处理内容
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
 //
 setTimeout(arguments.callee,100);
},100);*/
//这样处理效果明显好多了。
//以上就是重复定时器
//再来谈谈函数节流
function throttle(method,context){
 clearTimeout(method.tId);
 method.tId = setTimeout(function(){
 method.call(context);
 },100);
}
//该函数接受两个参数,第一个是要执行的函数,第二个是作用域。
//使用方法demo
//未使用情况:
window.onresize = function(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
//使用情况;
function resizeDiv(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
window.onresize = function(){
 throttle(resizeDiv);
};
//只要代码是周期性执行的,都应该使用节流。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript时间与日期操作技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • javascript中利用柯里化函数实现bind方法【推荐】

    • 柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: • 柯里化函数主要起到预处理的作用: • bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @par

  • javascript中利用柯里化函数实现bind方法

    柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @param con

  • 深入剖析JavaScript中的函数currying柯里化

    curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名).   柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程. 柯里化一个求和函数 按照分步求值,我们看一个简单的例子 var concat3Words = function (a, b, c) { r

  • JavaScript函数柯里化详解

    什么是柯里化 柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(译注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数. 柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callba

  • JavaScript高级函数应用之分时函数实例分析

    本文实例讲述了JavaScript高级函数应用之分时函数.分享给大家供大家参考,具体如下: 一.前提介绍: 某些函数是用户主动调用的,但因为一些客观的原因,这些函数会严重影响页面的性能. 二.应用场景: 在短时间内往页面中大量添加DOM节点显然会让浏览器吃不消,往往会导致浏览器的卡顿甚至假死. 三.解决方案: 以上述添加节点的例子来说明问题,我们将创建节点的工作分批进行,比如把1秒钟创建1000个节点,改为每隔200毫秒创建8个节点. 四.实现代码如下: var timeChunk = func

  • javascript中有趣的反柯里化深入分析

    写在前面的话:国内对前端的研究在某些方面也不逊色于国外,这篇文章虽然看不太懂,但我很欣赏这种深入研究的精神! 反科里化的话题来自javascript之父Brendan Eich去年的一段twitter. 近几天研究了一下,觉得这个东东非常有意思,分享一下.先忘记它的名字,看下它能做什么. 不要小看这个功能,试想下,我们在写一个库的时候,时常会写这样的代码,拿webQQ的Jx库举例. 我们想要的,其实只是借用Array原型链上的一些函数.并没有必要去显式的构造一个新的函数来改变它们的参数并且重新运

  • Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)

    Document自带的方法: 循环执行:var timeid = window.setInterval("方法名或方法","延时");window.clearInterval(timeid); 定时执行:var tmid = window.setTimeout("方法名或方法", "延时");window.clearTimeout(tmid); 举例说明: A.当要执行的方法中不需要参数时 复制代码 代码如下: <scr

  • JavaScript中的高级函数

    在JavaScript中,函数的功能十分强大.它们是第一类对象,也可以作为另一个对象的方法,还可以作为参数传入另一个函数,不仅如此,还能被一个函数返回!可以说,在JS中,函数无处不在,无所不能,堪比孙猴子呀!当你运用好函数时,它能助你取西经,让代码变得优雅简洁,运用不好时,那就遭殃了,要大闹天宫咯~ 除了函数相关的基础知识外,掌握一些高级函数并应用起来,不仅能让JS代码看起来更为精简,还可以提升性能.以下是小编总结的一些常用的.重要的高级函数,加上了一些个人见解,特此记录下来.如果您是JS初学者

  • javascript性能优化之分时函数的介绍

    分时函数和函数节流的问题不一样,函数节流针对的事件不是用户主动调用的,前面已经提过了. 函数节流的原理是:延迟当前函数的执行,如果该次延迟还没有完成,那么忽略接下来该函数的请求.也就是说会忽略掉很多函数请求. 在一些开发场景中,我们可能会一次性向文档中注入上千个节点,在短时间内向浏览器中大量添加DOM节点可能会让浏览器吃不消,结果往往会让浏览器卡顿或吃不消,解决方案之一便是使用分时函数(timeChunk). timeChunk分时函数让创建节点的工作分批进行,比如一秒钟创建1000个节点,改为

  • 深入解析JavaScript中函数的Currying柯里化

    引子 先来看一道小问题: 有人在群里出了到一道题目: var s = sum(1)(2)(3) ....... 最后 alert(s) 出来是6  var s = sum(1)(2)(3)(4) ....... 最后 alert(s) 出来是10  问sum怎么实现? 刚看到题目,我第一反应是sum返回的是一个function,但是没有最终实现,印象中看到过类似的原理,但是记不清了.   后来同事说,这个是叫柯里化, 实现方法比较巧妙: function sum(x){ var y = func

  • js定时器的使用(实例讲解)

    在javascritp中,有两个关于定时器的专用函数,分别为: 1.倒计定时器:timename=setTimeout("function();",delaytime);2.循环定时器:timename=setInterval("function();",delaytime); 第一个参数"function()"是定时器触发时要执行的动作,可以是一个函数,也可以是几个函数,函数间用":"隔开即可.比如要弹出两个警告窗口,便可将

随机推荐