防抖节流函数

防抖 debounce - 重新开始

应用场景:搜索框输入文字后调用对应搜索接口、文本编辑器实时保存

利用闭包,不管触发频率多高,在停止触发 n 秒后才会执行,如果重复触发,会清空之前的定时器,重新计时,直到最后一次 n 秒后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* @param {function} fn - 需要防抖的函数
* @param {number} time - 多长时间执行一次
* @param {boolean} flag - 第一次是否执行
*/
function debounce(fn, time, flag) {
let timer;
return function (...args) {
// 在time时间段内重复执行,会清空之前的定时器,然后重新计时
timer && clearTimeout(timer);
if (flag && !timer) {
// flag为true 第一次默认执行
fn.apply(this, args);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, time);
};
}

function fn(a) {
console.log("执行:", a);
}
let debounceFn = debounce(fn, 3000, true);
debounceFn(1);
debounceFn(2);
debounceFn(3);

// 先打印:执行: 1
// 3s后打印: 执行: 3

节流 throttle - 不要打断我

应用场景: 下拉滚动加载、快速点击、resize 事件,鼠标滑动、scroll 事件,视频播放记录时间等

利用闭包,不管触发频率多高,每隔一段时间内执行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
* @param {function} fn - 需要防抖的函数
* @param {number} time - 多长时间执行一次
* @param {boolean} flag - 第一次是否执行
*/
function throttle(fn, time, flag) {
let timer;
return function (...args) {
// flag控制第一次是否立即执行
if (flag) {
fn.apply(this, args);
// 第一次执行完后,flag变为false;否则以后每次都会执行
flag = false;
}
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
// 每次执行完重置timer
timer = null;
}, time);
}
};
}

// 测试
function fn() {
console.log("fn");
}
let throttleFn = throttle(fn, 3000, true);
setInterval(throttleFn, 500);

// 测试结果,一开始就打印"fn", 以后每隔3s打印一次"fn"