防抖和节流

debounce

上图是对鼠标进行监听,事件执行的很频繁,如果执行的事件是对接口的请求,那么会在短时间内发起大量重复请求,所以我们需要防抖或者节流进行解决。

防抖

防抖即为事件触发n秒后才执行事件,如果在n秒内又触发事件则重新计时

1. 手写版

1
2
3
4
5
6
7
8
9
function debounce(func, wait) {
let timer = null;
return () => {
clearTimeout(timer);
timer = setTimeout(()=> {
func.apply(this, arguments)
}, wait);
}
}

debounce-1

移动完n秒后才执行事件

2. 可立即执行版

触发事件立即执行,停止n秒后才可以重新触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function debounce(func, wait, immediate = true) {
let timer;

return () => {
if (timer) clearTimeout(timer);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(this, arguments);
}
else {
timer = setTimeout(() => {
func.apply(this, arguments);
}, wait);
}
}
}

debounce-4

节流

节流即为连续触发事件但是在n秒中只执行一次函数

1. 时间戳版

1
2
3
4
5
6
7
8
9
10
11
function throttle(func, wait) {
var previous = 0;

return () => {
var now = new Date();
if (now - previous > wait) {
func.apply(this, arguments);
previous = now;
}
}
}

当鼠标移入的时候,事件立刻执行,每过1s会执行一次,如果在2.2s停止触发,之后不会再执行事件。

throttle1

2. 定时器版

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(func, wait) {
var timeout;
var previous = 0;

return () => {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(this, arguments)
}, wait)
}
}
}

throttle2

可以看到使用定时器版本的节流函数,鼠标移入并不会立即执行,此后每移动1秒执行一次函数,在3.2秒左右移出鼠标,但是仍会在4秒时执行函数

参考

https://github.com/mqyqingfeng/Blog/issues/22
https://github.com/mqyqingfeng/Blog/issues/26

作者

Liang

发布于

2020-09-29

更新于

2021-12-24

许可协议


评论