为什么会有函数节流?
鼠标的mousemove、scroll,浏览器窗口的resize事件等,都是在短时间内重复触发。以onresize事件为例,若事件处理程序需要进行修改元素宽度高度等操作,那么频繁的触发事件会导致频繁的重绘页面。
DOM操作比非DOM交互需要更多的内存和CPU时间,连续尝试进行过多的DOM相关操作可能会导致浏览器挂起,有时候甚至会崩溃。为了解决这个问题,需要使用定时器对该函数进行节流。
函数节流背后的基本思想是:某些代码不可以在没有间断的情况下连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码,当第二次调用函数时,它会清除前一次的定时器并设置另一个。如果前一次的定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换成一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。
throttle()函数:自动地进行定时器的设置和清除。接收两个参数:要执行的函数和在哪个作用域执行。throttle()首先清除之前设置的任何定时器,定时器ID是存储在函数的tID属性中的,第一次把方法传递给throttle()函数的时候,这个属性可能并不存在。接下来,创建一个新的定时器,并将其ID存储在方法的tID属性中。如果这是第一次对这个方法调用throttle()的话,那么这段代码就会创建该属性。定时器代码使用call()来确保方法在适当的环境中执行。如果没有给出第二个参数,那么就在全局作用域内执行该方法
SetTimeOut
通过给setTimeout()设置一个合理的值,就能够在即时返馈与较高性能之间达成一个合理的折中。
$(document).ready(function() {
var timer = 0;
$(window).scroll(function() {
if (!timer) {
timer = setTimeout(function() {
checkScrollPosition();
timer = 0;
}, 250);
}
}).trigger('scroll');
});
我 们 没 有 直 接 将 checkScrollPosition() 设 置 为 scroll 事 件 处 理 程 序 , 而 是 使 用JavaScript的setTimeout函数,延迟250毫秒再调用它。更重要的是,我们会在执行任何代码之前先检查当前运行的计时器。因为检查一个简单变量的值速度极快,所以对事件处理程序的大多数调用都几乎能够立即返回。而对checkScrollPosition()函数的调用只会在计时器结束时才会发生,通常每次都要等250毫秒。
第二种方法 计时器
根据被节流的操作的特点,以及与页面的典型交互方式,我们可以直接给页面创建一个计时器,而不是等事件开始时再创建。
var scrolled = false;
$(window).scroll(function() {
scrolled = true;
});
setInterval(function() {
if (scrolled) {
checkScrollPosition();
scrolled = false;
}
}, 250);
checkScrollPosition();
});
与前面的节流代码不同,这个轮询式的方案会调用javascript的setInterval()函数,每250毫秒检查一次scrolled变量的状态。不管什么时候发生滚动事件, scrolled都会被设置为true,以确保在下一次轮询时调用checkScrollPosition()。
第三种方法:消除抖动
在频繁重复的事件发生期间限制处理次数的第三种技术叫消 除 抖动(debouncing)。这种技术是以电子开关重复发送信号必需的后处理技术命名的,可以确保在发生多个事件的情况下,最终只会有一个事件实际地起作用。
var searchTimeout,
searchDelay = 300;
$('#title').on('keyup', function(event) {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(function() {
$ajaxForm.triggerHandler('submit');// 发送Ajax请求
}, searchDelay);
}