一.什么是函数节流
限制一个函数在一定时间之内只能执行一次(这里做一下与函数防抖的区别:函数防抖是触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间)
二.函数节流使用场景
前端开发过程中,有一些事件或者函数,会被频繁地触发(短时间按内多次触发),最常见的例如,onresize,scroll,mousemove ,mousehover 等,这些事件的触发频率很高,不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会造成计算机资源的浪费,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。
除此之外,重复的 ajax 调用不仅可能会造成请求数据的混乱,还会造成网络拥塞,占用服务器带宽,增加服务器压力,显然这个问题也是需要解决的。
三.函数节流的思路
主要实现思路就是通过 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 throttle(fn, delay) {
let timer;
return function () {
var _this = this;
var args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fn.apply(_this, args); // 这里args接收的是外边返回的函数的参数,不能用arguments
// fn.apply(_this, arguments); 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。
timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
}, delay)
}
}
五.节流的使用场景
1.懒加载、滚动加载、加载更多或监听滚动条位置;
2.百度搜索框,搜索联想功能;
3.防止高频点击提交,防止表单重复提交;