1. 实现
1.1 节流
// 具体实战--监控平台展示信息(websocket大量吞吐)
let throttle = (fn, timmer = 1000) => {
let prevTime = new Date();
return (...args) => {
let nowTime = new Date();
if (nowTime - prevTime > timmer) {
fn.apply(this, args);
prevTime = nowTime;
}
};
};
1.2 防抖
// 具体实战--用户输入
let debounce = (fn, offset = 1000) => {
let timer = null;
return (...args) => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, offset);
};
};
2. 使用
let count = 1;
document.addEventListener(
'scroll',
throttle((event) => {
console.log(count++, event);
}),
false
);
3. 理解
- 由于
throttle()
执行了,所以返回的是return
里面的函数
-
throttle
里面包裹的匿名函数是实际被scroll
事件调用的函数
-
return
外部的变量prevTime
是闭包内的变量,能被return
函数内使用
-
this
指针问题
- 由于
...args
拿到的是数组,所以使用了apply
4. hooks写法
4.1 节流
import { useCallback, useEffect, useRef } from 'react';
const useThrottle = (fn: Function, delay: number, dep: any[] = []) => {
const { current } = useRef<{ fn: Function; prevTime: number }>({ fn, prevTime: Date.now() });
useEffect(() => {
// 若需要防抖的函数发生变动,或挂载点发生变动,重新挂载
current.fn = fn;
}, [current, fn]);
return useCallback(
(...args) => {
let nowTime = Date.now();
if (nowTime - current.prevTime > delay) {
current.fn.apply(this, args);
current.prevTime = nowTime;
}
},
[current, delay, ...dep]
);
};
export default useThrottle;
4.2 防抖
import { useCallback, useEffect, useRef } from 'react';
const useDebounce = (fn: Function, delay: number, dep: any[] = []) => {
const { current } = useRef<{ fn: Function; timer: NodeJS.Timeout | null }>({ fn, timer: null });
useEffect(() => {
// 若需要防抖的函数发生变动,或挂载点发生变动,重新挂载
current.fn = fn;
}, [current, fn]);
return useCallback(
(...args) => {
if (current.timer) {
clearTimeout(current.timer);
}
current.timer = setTimeout(() => {
current.fn.apply(this, args);
}, delay);
},
[current, delay, ...dep]
);
};
export default useDebounce;