Documentation
Framework
Version
Debouncer API Reference
Throttler API Reference
Rate Limiter API Reference
Queue API Reference
Batcher API Reference

asyncRateLimit

Function: asyncRateLimit()

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

Defined in: async-rate-limiter.ts:640

Creates an async rate-limited function that will execute the provided function up to a maximum number of times within a time window.

Async vs Sync Versions: The async version provides advanced features over the sync rate limit function:

  • Returns promises that can be awaited for rate-limited function results
  • Built-in retry support via AsyncRetryer integration
  • Abort support to cancel in-flight executions
  • Comprehensive error handling with onError callbacks and throwOnError control
  • Detailed execution tracking (success/error/settle counts, rejection counts)
  • More sophisticated window management with automatic cleanup

The sync rate limit function is lighter weight and simpler when you don't need async features, return values, or execution control.

What is Rate Limiting? Rate limiting allows a function to execute up to a limit within a time window, then blocks all subsequent calls until the window passes. This can lead to "bursty" behavior where all executions happen immediately, followed by a complete block.

Window Types:

  • 'fixed': A strict window that resets after the window period. All executions within the window count towards the limit, and the window resets completely after the period.
  • 'sliding': A rolling window that allows executions as old ones expire. This provides a more consistent rate of execution over time.

Configuration Options:

  • limit: Maximum number of executions allowed within the window (required)
  • window: Time window in milliseconds (required)
  • windowType: 'fixed' or 'sliding' (default: 'fixed')
  • enabled: Whether the rate limiter is enabled (default: true)
  • asyncRetryerOptions: Configure retry behavior for executions

When to Use Rate Limiting: Rate limiting is best used for hard API limits or resource constraints. For UI updates or smoothing out frequent events, throttling or debouncing usually provide better user experience.

  • A rate limiter will allow all executions until the limit is reached, then block all subsequent calls until the window resets
  • A throttler ensures even spacing between executions, which can be better for consistent performance
  • A debouncer collapses multiple calls into one, which is better for handling bursts of events

Error Handling:

  • If an onError handler is provided, it will be called with the error and rate limiter instance
  • If throwOnError is true (default when no onError handler is provided), the error will be thrown
  • If throwOnError is false (default when onError handler is provided), the error will be swallowed
  • Both onError and throwOnError can be used together - the handler will be called before any error is thrown
  • The error state can be checked using the underlying AsyncRateLimiter instance
  • Rate limit rejections (when limit is exceeded) are handled separately from execution errors via the onReject handler

State Management:

  • Uses TanStack Store for reactive state management
  • Use initialState to provide initial state values when creating the rate limiter
  • initialState can be a partial state object
  • Use onSuccess callback to react to successful function execution and implement custom logic
  • Use onError callback to react to function execution errors and implement custom error handling
  • Use onSettled callback to react to function execution completion (success or error) and implement custom logic
  • Use onReject callback to react to executions being rejected when rate limit is exceeded
  • The state includes execution times, success/error counts, and current execution status
  • State can be accessed via the underlying AsyncRateLimiter instance's store.state property
  • When using framework adapters (React/Solid), state is accessed from the hook's state property

Type Parameters

TFn extends AnyAsyncFunction

Parameters

fn

TFn

initialOptions

AsyncRateLimiterOptions<TFn>

Returns

Function

Attempts to execute the rate-limited function if within the configured limits. Will reject execution if the number of calls in the current window exceeds the limit.

Error Handling:

  • If the rate-limited function throws and no onError handler is configured, the error will be thrown from this method.
  • If an onError handler is configured, errors will be caught and passed to the handler, and this method will return undefined.
  • The error state can be checked using getErrorCount() and getIsExecuting().

Parameters

args

...Parameters<TFn>

Returns

Promise<undefined | ReturnType<TFn>>

A promise that resolves with the function's return value, or undefined if an error occurred and was handled by onError

Throws

The error from the rate-limited function if no onError handler is configured

Example

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

// First 5 calls will return a promise that resolves with the result
const result = await rateLimiter.maybeExecute('arg1', 'arg2');

// Additional calls within the window will return undefined
const result2 = await rateLimiter.maybeExecute('arg1', 'arg2'); // undefined
const rateLimiter = new AsyncRateLimiter(fn, { limit: 5, window: 1000 });

// First 5 calls will return a promise that resolves with the result
const result = await rateLimiter.maybeExecute('arg1', 'arg2');

// Additional calls within the window will return undefined
const result2 = await rateLimiter.maybeExecute('arg1', 'arg2'); // undefined

Example

ts
// Rate limit to 5 calls per minute with a sliding window
const rateLimited = asyncRateLimit(makeApiCall, {
  limit: 5,
  window: 60000,
  windowType: 'sliding',
  onError: (error) => {
    console.error('API call failed:', error);
  },
  onReject: (rateLimiter) => {
    console.log(`Rate limit exceeded. Try again in ${rateLimiter.getMsUntilNextWindow()}ms`);
  }
});

// First 5 calls will execute immediately
// Additional calls will be rejected until the minute window resets
// Returns the API response directly
const result = await rateLimited();

// For more even execution, consider using throttle instead:
const throttled = throttle(makeApiCall, { wait: 12000 }); // One call every 12 seconds
// Rate limit to 5 calls per minute with a sliding window
const rateLimited = asyncRateLimit(makeApiCall, {
  limit: 5,
  window: 60000,
  windowType: 'sliding',
  onError: (error) => {
    console.error('API call failed:', error);
  },
  onReject: (rateLimiter) => {
    console.log(`Rate limit exceeded. Try again in ${rateLimiter.getMsUntilNextWindow()}ms`);
  }
});

// First 5 calls will execute immediately
// Additional calls will be rejected until the minute window resets
// Returns the API response directly
const result = await rateLimited();

// For more even execution, consider using throttle instead:
const throttled = throttle(makeApiCall, { wait: 12000 }); // One call every 12 seconds
Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.

Bytes

No spam. Unsubscribe at any time.

Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.

Bytes

No spam. Unsubscribe at any time.