框架
版本
Debouncer API 参考
Throttler API 参考
速率限制器 API 参考
队列 API 参考
批处理器 API 参考
批处理器示例

asyncRateLimit

函数:asyncRateLimit()

ts
function asyncRateLimit<TFn>(fn, initialOptions): (...args) => Promise<undefined | ReturnType<TFn>>
function asyncRateLimit<TFn>(fn, initialOptions): (...args) => Promise<undefined | ReturnType<TFn>>

定义于:async-rate-limiter.ts:407

创建一个异步速率限制函数,该函数将在时间窗口内执行提供的函数达到最大次数。

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

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

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

请注意,与节流或防抖相比,速率限制是一种更简单的执行控制形式:

  • 速率限制器将允许所有执行,直到达到限制,然后阻止所有后续调用,直到窗口重置
  • 节流器确保执行之间的均匀间隔,这对于一致的性能可能更好
  • 防抖器将多个调用合并为一个,这更适合处理突发事件

如果需要更智能的执行控制,请考虑使用 throttle() 或 debounce()。当您特别需要强制执行时间段内执行次数的硬限制时,请使用速率限制。

错误处理:

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

类型参数

TFn extends AnyAsyncFunction

参数

fn

TFn

initialOptions

AsyncRateLimiterOptions<TFn>

返回

Function

如果符合配置的限制,则尝试执行速率限制函数。 如果当前窗口中的调用次数超出限制,则将拒绝执行。 如果允许执行,则在继续之前等待任何先前的执行完成。

错误处理:

  • 如果速率限制函数抛出错误并且未配置 onError 处理程序, 则此方法将抛出错误。
  • 如果配置了 onError 处理程序,错误将被捕获并传递给处理程序, 并且此方法将返回 undefined。
  • 如果超出速率限制,则将拒绝执行,并且如果已配置,则将调用 onReject 处理程序。
  • 可以使用 getErrorCount()getIsExecuting() 检查错误状态。
  • 可以使用 getRejectionCount() 跟踪速率限制拒绝。

参数

args

...Parameters<TFn>

返回

Promise<undefined | ReturnType<TFn>>

一个 Promise,它解析为函数的返回值,如果发生错误并由 onError 处理,则解析为 undefined

抛出

如果未配置 onError 处理程序,则抛出速率限制函数的错误

示例

ts
const rateLimiter = new AsyncRateLimiter(fn, { limit: 5, window: 1000 });

// 前 5 次调用将执行
await rateLimiter.maybeExecute('arg1', 'arg2');

// 窗口内的其他调用将被拒绝
await rateLimiter.maybeExecute('arg1', 'arg2'); // 已拒绝
const rateLimiter = new AsyncRateLimiter(fn, { limit: 5, window: 1000 });

// 前 5 次调用将执行
await rateLimiter.maybeExecute('arg1', 'arg2');

// 窗口内的其他调用将被拒绝
await rateLimiter.maybeExecute('arg1', 'arg2'); // 已拒绝

示例

ts
// 滑动窗口内每分钟限制 5 次调用
const rateLimited = asyncRateLimit(makeApiCall, {
  limit: 5,
  window: 60000,
  windowType: 'sliding',
  onError: (error) => {
    console.error('API 调用失败:', error);
  },
  onReject: (rateLimiter) => {
    console.log(`已超出速率限制。请在 ${rateLimiter.getMsUntilNextWindow()} 毫秒后重试`);
  }
});

// 前 5 次调用将立即执行
// 其他调用将被拒绝,直到分钟窗口重置
// 直接返回 API 响应
const result = await rateLimited();

// 要获得更均匀的执行,请考虑改用节流:
const throttled = throttle(makeApiCall, { wait: 12000 }); // 每 12 秒调用一次
// 滑动窗口内每分钟限制 5 次调用
const rateLimited = asyncRateLimit(makeApiCall, {
  limit: 5,
  window: 60000,
  windowType: 'sliding',
  onError: (error) => {
    console.error('API 调用失败:', error);
  },
  onReject: (rateLimiter) => {
    console.log(`已超出速率限制。请在 ${rateLimiter.getMsUntilNextWindow()} 毫秒后重试`);
  }
});

// 前 5 次调用将立即执行
// 其他调用将被拒绝,直到分钟窗口重置
// 直接返回 API 响应
const result = await rateLimited();

// 要获得更均匀的执行,请考虑改用节流:
const throttled = throttle(makeApiCall, { wait: 12000 }); // 每 12 秒调用一次