🐝函数防抖(debounce)和节流(throttle)

235 阅读4分钟

函数防抖(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); 


实现防抖节流封装的方法有许多种,我这里只是其中一种;仅供参考;

拜拜~

lb04.jpg