useThrottle.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. export interface DebounceAndThrottleOptions {
  2. // 立即执行
  3. immediate?: boolean;
  4. // 是否为debounce
  5. debounce?: boolean;
  6. // 只执行一次
  7. once?: boolean;
  8. }
  9. export type CancelFn = () => void;
  10. export type DebounceAndThrottleProcedure<T extends unknown[]> = (...args: T) => unknown;
  11. export type DebounceAndThrottleProcedureResult<T extends unknown[]> = [
  12. DebounceAndThrottleProcedure<T>,
  13. CancelFn
  14. ];
  15. import { isFunction } from '/@/utils/is';
  16. export function throttle<T extends unknown[]>(
  17. handle: DebounceAndThrottleProcedure<T>,
  18. wait: number,
  19. options: DebounceAndThrottleOptions = {}
  20. ): DebounceAndThrottleProcedureResult<T> {
  21. if (!isFunction(handle)) {
  22. throw new Error('handle is not Function!');
  23. }
  24. let { immediate = false } = options;
  25. const { once = false, debounce = false } = options;
  26. let timeoutId: ReturnType<typeof setTimeout> | undefined;
  27. // Has it been cancelled
  28. let cancelled: boolean | null = false;
  29. /**
  30. * @description: clear timer
  31. */
  32. function clearTimer() {
  33. if (timeoutId) {
  34. window.clearTimeout(timeoutId);
  35. timeoutId = undefined;
  36. }
  37. }
  38. /** cancel exec */
  39. function cancel() {
  40. clearTimer();
  41. cancelled = true;
  42. }
  43. // If once is true, only execute once
  44. function cancelExec(): void {
  45. once && cancel();
  46. }
  47. function fn(this: unknown, ...args: T) {
  48. // If it has been cancelled, it will not be executed
  49. if (cancelled) {
  50. return;
  51. }
  52. const exec = () => {
  53. !debounce && clearTimer();
  54. handle.apply(this, args);
  55. cancelExec();
  56. };
  57. if (immediate) {
  58. immediate = false;
  59. const callNow = !timeoutId;
  60. if (callNow) {
  61. exec();
  62. timeoutId = undefined;
  63. }
  64. } else {
  65. debounce && clearTimer();
  66. if (!timeoutId || debounce) {
  67. timeoutId = setTimeout(exec, wait);
  68. }
  69. }
  70. }
  71. return [fn, cancel];
  72. }
  73. export function useThrottle<T extends unknown[]>(
  74. handle: DebounceAndThrottleProcedure<T>,
  75. wait: number,
  76. options: DebounceAndThrottleOptions = {}
  77. ): DebounceAndThrottleProcedureResult<T> {
  78. return throttle(handle, wait, options);
  79. }