function createAsyncRateLimiter<TFn, TSelected>(
fn,
initialOptions,
selector): SolidAsyncRateLimiter<TFn, TSelected>
function createAsyncRateLimiter<TFn, TSelected>(
fn,
initialOptions,
selector): SolidAsyncRateLimiter<TFn, TSelected>
Defined in: async-rate-limiter/createAsyncRateLimiter.ts:129
A low-level Solid hook that creates an AsyncRateLimiter instance to limit how many times an async function can execute within a time window.
This hook is designed to be flexible and state-management agnostic - it simply returns a rate limiter instance that you can integrate with any state management solution (createSignal, etc).
Rate limiting is a simple approach that 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.
The rate limiter supports two types of windows:
Unlike the non-async RateLimiter, this async version supports returning values from the rate-limited function, making it ideal for API calls and other async operations where you want the result of the maybeExecute call instead of setting the result on a state variable from within the rate-limited function.
For smoother execution patterns, consider using:
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.
Error Handling:
The hook uses TanStack Store for reactive state management. The selector parameter allows you to specify which state changes will trigger a re-render, optimizing performance by preventing unnecessary re-renders when irrelevant state changes occur.
By default, there will be no reactive state subscriptions and you must opt-in to state tracking by providing a selector function. This prevents unnecessary re-renders and gives you full control over when your component updates. Only when you provide a selector will the component re-render when the selected state values change.
Available state properties:
• TFn extends AnyAsyncFunction
• TSelected = {}
TFn
AsyncRateLimiterOptions<TFn>
(state) => TSelected
SolidAsyncRateLimiter<TFn, TSelected>
// 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();
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.