函数防抖与节流
2022-03-01
2851
函数防抖(debounce)
- 应用场景
- 在用户停止输入后,才进行表单验证
- 搜索框连续输入关键字,只有当停止输入后,才进行http访问,否则ajax交互太频繁
- 定义
当触发后再次触发,会取消上一次触发的执行,直到最后一次触发后过去设定时间后才执行。
- 实现思路
当事件触发之后,必须等待设定的时间间隔之后,回调函数才会执行,假若在等待的时间内,事件又触发了则重新再等待设定的时间间隔,直到事件在设定的时间间隔内事件不被触发,那么最后一次触发事件后,则执行函数。
第一次调用函数,创建一个定时器,将需要执行的目标函数放到定时器里,在指定的时间间隔之后执行目标函数。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。目的是只有在执行函数的请求停止了一段时间之后才执行。
1 |
|
使用:
eg. 监听滚动事件
1 |
|
函数节流(throttle)
- 应用场景
- 避免用户多次点击按钮时,重复提交表单
- 监控浏览器窗口大小(resize)
- 定义
当事件持续触发时,函数在一定时间间隔内(例如 n 秒)只执行一次,在这 n 秒内 无视后来产生的函数调用请求,也不会延长时间间隔。 - 实现思路
- 时间戳
在闭包函数的外部存储了一个previous变量(初始值为0)记录上次执行的时间戳,每次触发内部闭包函数时与上次的时间戳进行对比判断,如果间隔时间大于我们设置的等待时间,则执行函数,同时更新时间戳。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 时间戳版
function throttle(fn, wait) {
var context;
// 上一次执行 fn 的时间
var previous = 0;
return function (...args) {
// 获取当前时间,转换成时间戳,单位毫秒
var now = +new Date();
context = this;
// 将当前时间和上一次执行函数的时间进行对比
// 大于等待时间就把 previous 设置为当前时间并执行函数 fn
if (now - previous > wait) {
fn.apply(context, args);
previous = now;
}
}
}
- 定时器
触发事件时,设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执行,然后执行函数,清空定时器,这样就可以设置下个定时器。
两个版本的节流函数最大的不同就是:函数执行的时间点,定时器版本由于setTimeout延时的特性,是在时间段结束时执行目标函数,而时间戳版本是在时间段开始时执行。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 定时器版
function throttle(fn, wait) {
let timer;
return function (...args) {
let context = this;
if (!timer) {
timer = setTimeout(function() {
// clearTimeout(timeout) 并不会把 timeout 设为 null
// 手动设置,便于后续判断
timer = null;
// apply() 的第二个参数需要的是类数组,故不需要...args
fn.apply(context, args)
}, wait)
}
}
}
和防抖函数每次清除timer不同,节流函数对timer进行非空判断,只有它为空的时候才能设置定时器,这样保证了在一段时间内同时只有一个定时器。
debounce 和 throttle 区别
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
- 本文作者:JSZ
- 本文链接:blog.vampuck.com/2022/03/01/throttle_debounce/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!
查看评论