节流,顾名思义,控制水的流量。控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流(Rate Limit)类似。
想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些节流的场景呢:
- scroll 事件,每隔一秒计算一次位置信息等。
- 浏览器播放事件,每隔一秒计算一次进度信息等。
- input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求(也可做防抖)。
代码如下,可以看出来节流重在开关锁, timer=null。
// 节流可以理解为「倒计时中」
const throttle = (fn, time) => {
let timer = null; // 设置一个倒计时的计时器
// 返回一个包装后的节流函数
return (...args) => {
if (timer) return; // 如果此时已开始计时则什么都不做
fn.call(undefined, ...args); // 计时结束,就调用原函数
// 需要重新设置定时器,并在指定的时间之后清空
timer = setTimeout(() => {
timer = null;
}, time);
};
};
防抖 debounce
防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。
- 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖。
- 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖。
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存。
代码如下,可以看出来防抖重在清零,clearTimeout(timer)。
// 防抖可以理解为「响应事件被打断」
const debounce = (fn, time) => {
let timer = null; // 设置一个计时器
// 返回一个包装后的防抖函数
return (...args) => {
// 如果此时已开始计时,就清空定时器
if (timer !== null) clearTimeout(timer);
// 重新设置定时器,并在相应时间执行原函数后清空
timer = setTimeout(() => {
fn.call(undefined, ...args);
timer = null;
}, time);
};
};