节流&防抖

235 阅读1分钟

节流 throttle

  • 应用: 滚动/拖拽时减少触发频率
  • 相当于技能CD
  • throttle body: 汽车节气门

Edit 节流

封装


function throttle(cb: Function, time = 1000) {
  let cd = false;
  return function (...args: any[]) {
    if (cd) return;
    cd = true;
    cb.call(this, ...args); // 透传this
    setTimeout(() => (cd = false), time);
  };
}

使用

btn.addEventListener(
  "click",
  throttle((e) => console.log(e))
);

防抖(dou) debounce

  • 应用: 搜索框
  • 延迟执行
  • 类似于憋大招前的吟唱. 如果大招cd为0, 那么一直不停按大招键,大招将永远释放不出来
  • 如果你的只点了一下鼠标就出现了双击,这个时候就需要调整一下你鼠标的debounce time

Edit 防抖

写法一

export const useDebounce = (value: any, delay = 300) => {
  const [v, setV] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setV(value);
    }, delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return v;
};
cosnt [value, setV] = useState(1)
cosnt debounceValue = useDebounce(value)

写法二

export const useDebounceFn = (cb: Function, delay = 300) => {
  const timer = useRef<any>(null);

  return (...args: any) => {
    clearTimeout(timer.current);
    timer.current = setTimeout(() => {
      cb.call(undefined, ...args);
      clearTimeout(timer.current);
    }, delay);
  };
};
const fetchSuggest = useDebounceFn((value: string) => {
  ...
  ...
});

function onChange(e) {
  const value = e.target.value;
  setV(value);
  fetchSuggest(value);
}

写法三

function debounce(cb: Function, delay = 1000) {
  let timer: any;

  return function (...args) {
    clearTimeout(timer);

    timer = setTimeout(() => {
      cb.apply(this, args); // 透传this, args
    }, delay);
  };
}

使用

document.getElementById("btn").addEventListener(
  "click",
  debounce((e) => console.log(e))
);

注意: 

  • 写法3在react中使用时记得用useCallback将函数缓存起来, 不然每次render都会把timer清空
  • react中推荐使用方法1和2
    const fetchSuggest = useCallback(debounceFn((value: string) => {
      ...
      ...
    }))