框架
版本
防抖器 API 参考
节流器 API 参考
速率限制器 API 参考
队列 API 参考
批处理器 API 参考

使用异步节流器

函数:useAsyncThrottler()

ts
function useAsyncThrottler<TFn, TSelected>(
   fn, 
   options, 
selector): ReactAsyncThrottler<TFn, TSelected>
function useAsyncThrottler<TFn, TSelected>(
   fn, 
   options, 
selector): ReactAsyncThrottler<TFn, TSelected>

定义于:react-pacer/src/async-throttler/useAsyncThrottler.ts:160

一个低级别的 React hook,用于创建一个 AsyncThrottler 实例,以限制异步函数的执行频率。

此 hook 设计得非常灵活且与状态管理无关——它只返回一个节流器实例,您可以将其集成到任何状态管理解决方案中(useState、Redux、Zustand、Jotai 等)。

异步节流确保异步函数在一个指定的时间窗口内最多执行一次,无论它被调用多少次。这对于对昂贵的 API 调用、数据库操作或其他异步任务进行速率限制非常有用。

与非异步 Throttler 不同,此异步版本支持从节流函数返回值,这使其成为 API 调用和其他异步操作的理想选择,您可以在其中获取 maybeExecute 调用的结果,而不是在节流函数内部将结果设置到状态变量中。

错误处理

  • 如果提供了 onError 处理程序,它将与错误和节流器实例一起被调用
  • 如果 throwOnError 为 true(当没有提供 onError 处理程序时的默认值),错误将被抛出
  • 如果 throwOnError 为 false(当提供 onError 处理程序时的默认值),错误将被吞没
  • onError 和 throwOnError 可以一起使用 - 在任何错误被抛出之前,处理程序都会被调用
  • 错误状态可以通过底层 AsyncThrottler 实例进行检查

状态管理和选择器

该 hook 使用 TanStack Store 进行响应式状态管理。selector 参数允许您指定哪些状态更改将触发重新渲染,从而通过防止不相关的状态更改引起不必要的重新渲染来优化性能。

默认情况下,不会有任何响应式状态订阅,您必须通过提供选择器函数来选择启用状态跟踪。这可以防止不必要的重新渲染,并让您完全控制组件的更新时间。只有当您提供选择器时,组件才会在选定的状态值发生变化时重新渲染。

可用的状态属性

  • errorCount:导致错误的函数执行次数。
  • isExecuting:节流函数当前是否正在异步执行
  • isPending:节流器是否正在等待超时触发执行
  • lastArgs: Последний вызов maybeExecute 的参数
  • lastExecutionTime:函数最后执行时间的戳(毫秒)
  • lastResult:最近一次成功函数执行的结果。
  • nextExecutionTime:下次可以执行的时间戳(毫秒)
  • settleCount:已完成(成功或错误)的函数执行次数
  • status:当前执行状态('disabled' | 'idle' | 'pending' | 'executing' | 'settled')。
  • successCount:成功完成的函数执行次数。

类型参数

TFn extends AnyAsyncFunction

TSelected = {}

参数

fn

TFn

options

AsyncThrottlerOptions<TFn>

选择器

(state) => TSelected

Returns (返回)

ReactAsyncThrottler<TFn, TSelected>

示例

tsx
// Default behavior - no reactive state subscriptions
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data; // Return value is preserved
  },
  { wait: 1000 }
);

// Opt-in to re-render when execution state changes (optimized for loading indicators)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    isExecuting: state.isExecuting,
    isPending: state.isPending,
    status: state.status
  })
);

// Opt-in to re-render when results are available (optimized for data display)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    lastResult: state.lastResult,
    successCount: state.successCount,
    settleCount: state.settleCount
  })
);

// Opt-in to re-render when error state changes (optimized for error handling)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  {
    wait: 1000,
    onError: (error) => console.error('API call failed:', error)
  },
  (state) => ({
    errorCount: state.errorCount,
    status: state.status
  })
);

// Opt-in to re-render when timing information changes (optimized for timing displays)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    lastExecutionTime: state.lastExecutionTime,
    nextExecutionTime: state.nextExecutionTime
  })
);

// With state management and return value
const [data, setData] = useState(null);
const { maybeExecute, state } = useAsyncThrottler(
  async (query) => {
    const result = await searchAPI(query);
    setData(result);
    return result; // Return value can be used by the caller
  },
  {
    wait: 2000,
    leading: true,   // Execute immediately on first call
    trailing: false  // Skip trailing edge updates
  }
);

// Access the selected state (will be empty object {} unless selector provided)
const { isExecuting, lastResult } = state;
// Default behavior - no reactive state subscriptions
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data; // Return value is preserved
  },
  { wait: 1000 }
);

// Opt-in to re-render when execution state changes (optimized for loading indicators)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    isExecuting: state.isExecuting,
    isPending: state.isPending,
    status: state.status
  })
);

// Opt-in to re-render when results are available (optimized for data display)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    lastResult: state.lastResult,
    successCount: state.successCount,
    settleCount: state.settleCount
  })
);

// Opt-in to re-render when error state changes (optimized for error handling)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  {
    wait: 1000,
    onError: (error) => console.error('API call failed:', error)
  },
  (state) => ({
    errorCount: state.errorCount,
    status: state.status
  })
);

// Opt-in to re-render when timing information changes (optimized for timing displays)
const asyncThrottler = useAsyncThrottler(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data;
  },
  { wait: 1000 },
  (state) => ({
    lastExecutionTime: state.lastExecutionTime,
    nextExecutionTime: state.nextExecutionTime
  })
);

// With state management and return value
const [data, setData] = useState(null);
const { maybeExecute, state } = useAsyncThrottler(
  async (query) => {
    const result = await searchAPI(query);
    setData(result);
    return result; // Return value can be used by the caller
  },
  {
    wait: 2000,
    leading: true,   // Execute immediately on first call
    trailing: false  // Skip trailing edge updates
  }
);

// Access the selected state (will be empty object {} unless selector provided)
const { isExecuting, lastResult } = state;
我们的合作伙伴
Code Rabbit
Unkey
订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

无垃圾邮件。您可以随时取消订阅。

订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

无垃圾邮件。您可以随时取消订阅。