浏览器中某些计算和处理要比其他的昂贵很多,例如DOM操作、AJAX请求等。
函数节流的基本思想是,某些代码不可以没有间断的情况下连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次条用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有再执行函数的请求停止了一段时间之后才执行。以下是该模式的基本形式:
var processor = {
timeoutId: null,
// 实际进行处理的方法
performProcessing: function () {
// 实际执行的代码
},
// 初始处理调用的方法
process: function () {
clearTimeout(this.timeoutId)
var _this = this
this.timeoutId = setTimeout(function () {
_this.performProcessing()
}, 100)
}
}
// 尝试开始执行
processor.process()
以上这个方法时间间隔设置为100ms,如果100ms内调用了多次process(),实际上仍然只会被调用一次。
这个模式可以使用throttle()函数来简化,这个函数可以自动进行定时器的设置和清除。如下:
function throttle(method, context) {
clearTimeout(method.tId)
methods.tId = setTimeout(function () {
method.call(context)
}, 100)
}
节流的使用场景
节流在resize事件中是最常用的。改变页面布局频繁相当于操作DOM,会消耗大量CPU资源。例如,一个div元素需要保持它的高度始终等于宽度。实现代码如下:
window.onresize = function () {
var div = document.getElementById('myDiv')
div.style.height = div.offsetWidth + 'px'
}
这段代码如果该元素上有非常复杂的CSS,这个过程的计算将会很复杂。使用throttle()函数来优化:
function resizeDiv() {
var div = document.getElementById('myDiv')
div.style.height = div.offsetWidth + 'px'
}
window.onresize = function() {
throttle(resizeDiv)
}
只要代码是周期性执行的,都应该使用节流,但是不能控制请求执行的速率。