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

createAsyncRateLimiter

函数:createAsyncRateLimiter()

ts
function createAsyncRateLimiter<TFn, TSelected>(
   fn, 
   initialOptions, 
selector): SolidAsyncRateLimiter<TFn, TSelected>
function createAsyncRateLimiter<TFn, TSelected>(
   fn, 
   initialOptions, 
selector): SolidAsyncRateLimiter<TFn, TSelected>

定义于:async-rate-limiter/createAsyncRateLimiter.ts:129

一个低级别的 Solid hook,用于创建一个 AsyncRateLimiter 实例,以限制异步函数在某个时间窗口内可以执行的次数。

此 hook 设计得非常灵活且与状态管理无关——它只是返回一个速率限制器实例,您可以将其集成到任何状态管理解决方案中(createSignal 等)。

速率限制是一种简单的方法,允许函数在一个时间窗口内执行最多达到限制次数,然后阻止所有后续调用,直到窗口期结束。这可能导致“突发”行为,即所有执行立即发生,然后是完全的阻塞。

速率限制器支持两种类型的窗口

  • 'fixed': 一个严格的窗口,在窗口期后重置。窗口内的所有执行都会计入限制,并且窗口会在期满后完全重置。
  • 'sliding': 一个滚动窗口,允许在旧的执行过期时进行新的执行。这提供了更一致的执行速率。

与非异步的 RateLimiter 不同,此异步版本支持从被速率限制的函数返回结果,使其非常适合 API 调用和其他异步操作,如果您希望在调用 maybeExecute 时获得结果,而不是在被速率限制的函数内部将结果设置到状态变量中。

为了更平滑的执行模式,请考虑使用

  • 节流 (Throttling): 确保执行之间有规律的间隔(例如,最多每 200 毫秒一次)
  • 防抖 (Debouncing): 在调用暂停后执行(例如,在没有调用 500 毫秒后)

速率限制最适合用于硬性的 API 限制或资源约束。对于 UI 更新或平滑频繁的事件,节流或防抖通常能提供更好的用户体验。

错误处理

  • 如果提供了 onError 处理程序,它将使用错误和速率限制器实例被调用
  • 如果 throwOnError 为 true(当没有提供 onError 处理程序时的默认值),错误将被抛出
  • 如果 throwOnError 为 false(当提供 onError 处理程序时的默认值),错误将被吞没
  • onError 和 throwOnError 可以一起使用 - 在任何错误被抛出之前,处理程序都会被调用
  • 可以使用底层的 AsyncRateLimiter 实例检查错误状态
  • 速率限制拒绝(当超出限制时)与执行错误分开处理,通过 onReject 处理程序。

状态管理和选择器

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

默认情况下,不会进行任何响应式状态订阅,您必须通过提供一个 selector 函数来选择启用状态跟踪。这可以防止不必要的重新渲染,并让您完全控制组件何时更新。只有当您提供了一个 selector 时,组件才会根据所选状态值的变化而重新渲染。

可用的状态属性

  • currentWindowStart: 当前窗口开始的时间戳
  • executionCount: 已完成的函数执行次数
  • hasError: 上次执行是否导致错误
  • isExecuting: 当前是否有异步函数执行正在进行中
  • lastError: 最近一次失败执行的错误(如果有)
  • lastResult: 最近一次成功执行的结果
  • nextWindowTime: 下一个窗口开始的时间戳
  • rejectionCount: 由于速率限制而被拒绝的函数调用次数
  • remainingInWindow: 当前窗口中剩余的执行次数

类型参数

TFn extends AnyAsyncFunction

TSelected = {}

参数

fn

TFn

initialOptions

AsyncRateLimiterOptions<TFn>

选择器

(state) => TSelected

Returns (返回)

SolidAsyncRateLimiter<TFn, TSelected>

示例

tsx
// Default behavior - no reactive state subscriptions
const { maybeExecute } = createAsyncRateLimiter(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data; // Return value is preserved
  },
  { limit: 5, window: 1000 } // 5 calls per second
);

// Opt-in to re-render when rate limit and execution state changes (optimized for UI feedback)
const rateLimiter = createAsyncRateLimiter(
  async (query) => {
    const result = await searchAPI(query);
    return result;
  },
  { limit: 10, window: 60000 },
  (state) => ({
    remainingInWindow: state.remainingInWindow,
    isExecuting: state.isExecuting,
    rejectionCount: state.rejectionCount
  })
);

// Opt-in to re-render when error state changes (optimized for error handling)
const rateLimiter = createAsyncRateLimiter(
  async (query) => {
    const result = await searchAPI(query);
    return result;
  },
  {
    limit: 10,
    window: 60000, // 10 calls per minute
    onReject: (info) => console.log(`Rate limit exceeded: ${info.nextValidTime - Date.now()}ms until next window`)
  },
  (state) => ({ hasError: state.hasError, lastError: state.lastError })
);

// Access the selected state (will be empty object {} unless selector provided)
const { remainingInWindow, isExecuting } = rateLimiter.state();
// Default behavior - no reactive state subscriptions
const { maybeExecute } = createAsyncRateLimiter(
  async (id: string) => {
    const data = await api.fetchData(id);
    return data; // Return value is preserved
  },
  { limit: 5, window: 1000 } // 5 calls per second
);

// Opt-in to re-render when rate limit and execution state changes (optimized for UI feedback)
const rateLimiter = createAsyncRateLimiter(
  async (query) => {
    const result = await searchAPI(query);
    return result;
  },
  { limit: 10, window: 60000 },
  (state) => ({
    remainingInWindow: state.remainingInWindow,
    isExecuting: state.isExecuting,
    rejectionCount: state.rejectionCount
  })
);

// Opt-in to re-render when error state changes (optimized for error handling)
const rateLimiter = createAsyncRateLimiter(
  async (query) => {
    const result = await searchAPI(query);
    return result;
  },
  {
    limit: 10,
    window: 60000, // 10 calls per minute
    onReject: (info) => console.log(`Rate limit exceeded: ${info.nextValidTime - Date.now()}ms until next window`)
  },
  (state) => ({ hasError: state.hasError, lastError: state.lastError })
);

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

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

Bytes

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

订阅 Bytes

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

Bytes

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