函数防抖(debounce)和节流(throttle)
大纲
1.简介
2.应用场景
3.代码封装
注:
本篇是我对防抖节流的理解,仅供参考;
本篇如果有不对的地方请各位 大佬 指出;感谢;
✍创作不易,如果本篇帮到了您,请点个👍支持一下;感谢;
1.简介
防抖(debounce)
函数在 n 秒后执行;如果在 n 秒内函数频繁重复触发,则重新及时;
节流(throttle)
函数n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效;
比喻
防抖:公交车在每站停靠时等待乘客上车,直到没有人再上车为止,车才会启动。
节流:地铁每站停留的时间是固定的,即使还有人想上车,一旦时间到了,地铁就会准时开走。
两者的区别
防抖:关注的是“延迟执行”,即在事件停止后才执行。
节流:关注的是“定时执行”,即在一定时间内只执行一次。
作用
都是在高频事件中防止函数被多次调用,是一种性能优化的方案。
2.应用场景
高频事件
比如 window 对象的 resize、scroll 事件,拖拽时的 mousemove 事件等;
表单验证、提交按钮、窗口缩放、文字输入、自动完成的 keyup 等事件;
防抖的应用场景
输入框搜索
用户在输入框中输入搜索关键词时,使用防抖可以避免每个字符输入后都发送请求,而是在用户停止输入一段时间后才发送一次请求。
表单提交
防止用户多次点击提交按钮导致多次提交表单,确保只在最后一次点击后执行提交。
窗口调整大小
当用户调整浏览器窗口大小时,使用防抖可以避免频繁计算布局,直到用户停止调整。
下拉加载
在滚动到页面底部时,使用防抖避免重复加载数据,只有在停止滚动后再执行加载操作。
组件的状态变化
在用户输入内容或修改某些设置后,可以使用防抖来推迟状态的更新,避免频繁重新渲染组件。
节流的应用场景
滚动事件
在用户滚动页面时,使用节流可以限制事件处理函数的执行频率,减少性能开销,避免因快速滚动导致多次执行。
窗口滚动
当用户滚动浏览器窗口时,使用节流可以确保每隔一定时间只处理一次事件,例如更新当前滚动位置。
按钮点击
控制用户点击按钮的频率,例如防止用户连续快速点击某个按钮导致多次触发事件。
动画效果
在处理一些动画效果时,可以使用节流来控制动画的执行频率,使动画效果更加流畅。
网络请求
在实时数据更新(如数据监控)时,使用节流可以限制请求的频率,确保在一段时间内只发送一次请求,避免服务器负担过重。
3.代码封装
防抖(debounce)
/**
* 函数防抖
* @param {Function} fn
* @param {Number} delay
* @returns {Function}
*/
const debounce = (fn, delay = 500) => {
if (typeof fn !== 'function') {
throw new TypeError('形参 fn 不是一个函数');
}
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
};
// 使用示例:
const log = message => console.log(message);
const debounceLog = debounce(log);
// 循环调用 debounce
for (i = 1; i < 9999; i++) {
console.log('当前i是' + (i+1));
debounceLog('防抖:测试消息');
};
节流(throttle)
const throttle = (fn, delay = 500) => {
if (typeof fn !== 'function') {
throw new TypeError('Expected a function');
}
if (typeof delay !== 'number' || delay < 0) {
throw new TypeError('Expected delay to be a non-negative number');
}
let lastTime = 0; // 初始化为0,确保第一次调用立即执行
return function (...args) { // 使用函数保持正确的this上下文
let now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
};
// 使用示例
const log = (message) => console.log(message);
const throttledLog = throttle(log, 1000);
// 每300毫秒触发,但每1000毫秒只会执行一次
setInterval(() => throttledLog("节流:测试消息"), 300);
注
实现防抖节流封装的方法有许多种,我这里只是其中一种;仅供参考;
拜拜~