一,什么是函数节流
概念:限制一个函数在一定时间内只能执行一次。
举个例子,坐火车或地铁,过安检的时候,在一定时间(例如10秒)内,只允许一个乘客通过安检入口,以配合安检人员完成安检工作。上例中,每10秒内,仅允许一位乘客通过,分析可知,“函数节流”的要点在于,在 一定时间 之内,限制 一个动作 只 执行一次 。
二,为什么需要函数节流
原因:
开发过程中,有一些事件或者函数,会被频繁地触发(短时间按内多次触发),最常见的例如,onresize,scroll,mousemove ,mousehover 等,这些事件的触发频率很高,不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会造成计算机资源的浪费,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。
三,函数节流如何解决上述问题
主要实现思路就是通过 setTimeout 定时器,通过设置延时时间,在第一次调用时,创建定时器,先设定一个变量true,写入需要执行的函数。第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为false。那么下次判断变量时则为false,函数会依次运行。目的在于在一定的时间内,保证多次函数的请求只执行最后一次调用。
四,代码实现函数节流
/ 时间戳方案
function throttle(fn,wait){
var pre = Date.now();
return function(){
var context = this;
var args = arguments;
var now = Date.now();
if( now - pre >= wait){
fn.apply(context,args);
pre = Date.now();
}
}
}
function handle(){
console.log(Math.random());
}
// 定时器方案
function throttle(fn,wait){
var timer = null;
return function(){
var context = this;
var args = arguments;
if(!timer){
timer = setTimeout(function(){
fn.apply(context,args);
timer = null;
},wait)
}
}
}
function handle(){
console.log(Math.random());
}
第三种方案,代码实现如下,代码健壮性更强一些
const throttle = (func, time = 17,
options = {
leading: true,
trailing: false,
context: null
}) => {
let previous = new Date(0).getTime()
let timer;
const _throttle = function(...args) {
let now = new Date().getTime();
console.log(now - previous)
if (!options.leading) {
if (timer) return;
timer = setTimeout(() => {
timer = null;
func.apply(options.context, args)
}, time)
} else if (now - previous > time) {
func.apply(options.context, args)
previous = now;
} else if (options.trailing) {
clearTimeout(timer)
timer = setTimeout(() => {
func.apply(options.context, args)
}, time)
}
}
_throttle.cancel = () => {
previous = 0;
clearTimeout(timer);
timer = null;
}
return _throttle;
}
let fn = () => {
console.log('boom')
}
let myThrottle = throttle(fn, 10000);
function toSave() {
myThrottle();
}