# 08-防抖和节流
# 是什么
本质上是优化高频率执行代码的一种手段
如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率
- 防抖: n 秒后再执行该事件,若在 n 秒内被重复触发,则重新计时
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
# 防抖
高频触发事件,结束一定时间后,只执行最后一次触发
// 防抖简易实现
let debounce = function (fn, delay) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
timer = null;
};
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
// 防抖立即执行版
let debounce = function(fn, wait = 1000, immediate = false) {
let timer = null;
return function() {
if (timer) {
clearTimeout(timer);
}
if (immediate) {
let callNow = !timer;
timer = setTimeout(()=>{
timer = null;
}, wait);
if (callNow) {
fn.apply(this, arguments);
}
} else {
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 节流
- 时间戳写法,事件会立即执行,停止触发后没有办法再次执行
// 节流简易实现
let throttle = function (fn, delay) {
let oldtime = Date.now()
return function (...args) {
let newtime = Date.now()
if (newtime - oldtime >= delay) {
fn.apply(null, args)
oldtime = Date.now()
}
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 定时器写法,
delay
毫秒后第一次执行,第二次事件停止触发后依然会再一次执行
// 节流简易实现
let throttle = function (fn, delay) {
let timer = null
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args)
timer = null
}, delay);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 应用场景
# 防抖:
- 搜索框实时搜索:当用户在搜索框中输入关键词时,防抖技术能够确保在用户输入完成后的一段时间内(如50毫秒)再发出请求,而不是连续不断地发送请求。
- 窗口调整事件:当用户的浏览器窗口被放大或缩小时,防抖技术会在用户停止调整窗口大小一段时间后再执行相应的回调函数。
- 表单验证:在使用表单进行数据录入时,防抖技术可以在用户停止输入一段时间(如1秒)后再进行表单内容的验证。
# 节流:
- 滚动事件:在页面滚动时,节流技术可以减少滚动事件的触发频率,从而降低回调函数的执行次数,提高页面的性能。
- 鼠标移动事件:在鼠标移动时,节流技术可以控制回调函数的执行频率,以避免不必要的频繁调用。
- 点击按钮防止重复提交:当用户点击按钮时,节流技术能够限制每次点击之间的间隔,防止用户因为快速多次点击而造成重复提交操作。