函数防抖(debounce): 触发高频事件后n秒内只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
函数节流(throttle):高频事件触发,但是在n秒内只会执行一次
函数节流与函数防抖都是为了限制函数的执行频次。以优化函数触发频率过高导致响应速度跟不上 出现延迟卡顿的现象
实际开发中需要防抖处理的场景还是非常多的,如resize事件、scroll事件、input事件、拖拽事件等。除了这些,还有很多情况需要我们结合实际开发处理。
// 防抖函数
const handlerScroll = function () {
var scrollTop =
document.body.scrollTop || document.documentElement.scrollTop;
console.log("滚动条当前位置" + scrollTop);
};
function debounce(fn, delay) {
let timer = null; //借助于闭包
return function () {
// 每次执行前先清除定时器 以确保delay时间内fn函数不被执行
timer && clearTimeout(timer);
// 多次调用会重新计时
timer = setTimeout(fn, delay);
};
}
const scrollHandler = debounce(handlerScroll, 1000);
window.addEventListener("scroll", scrollHandler);
// 节流
function throttle(fn, delay) {
let timer = null;
return function () {
let context = this;
let args = arguments;
// 判断timer 没有到等待时间不能执行
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, delay);
}
};
}
const scrollEvent = function () {
console.log("当前时间戳" + new Date().getTime());
};
const scrollHandler = throttle(scrollEvent, 1000);
// 滚动事件
window.addEventListener("scroll", scrollHandler);
使用RXJS纯函数的方式实现防抖与节流
import {fromEvent} from 'rxjs';
import {pluck, debounceTime} from 'rxjs/operators';
// 防抖
const searchInput = document.getElementById('search');
// fromEvent是将事件转换成 observable 序列
const searchInput$ = fromEvent(searchInput,'keyup').pipe(
pluck('target','value'),
// 直接调用防抖函数
debounceTime(1000)
)
searchInput$.subscribe(
value => console.log(`我触发后每间隔一秒时间才会执行哦,当前输入的值为${value}`)
)
------------------------------------------------------------------------------------
// 节流
const scroll$ = fromEvent(window,'scroll').pipe(
throttleTime(1000)
)
scroll$.subscribe(
_ => console.log('我一开始就触发,持续触发时一秒内只执行一次')
)