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 等)。
速率限制是一种简单的方法,允许函数在一个时间窗口内执行最多达到限制次数,然后阻止所有后续调用,直到窗口期结束。这可能导致“突发”行为,即所有执行立即发生,然后是完全的阻塞。
速率限制器支持两种类型的窗口
与非异步的 RateLimiter 不同,此异步版本支持从被速率限制的函数返回结果,使其非常适合 API 调用和其他异步操作,如果您希望在调用 maybeExecute 时获得结果,而不是在被速率限制的函数内部将结果设置到状态变量中。
为了更平滑的执行模式,请考虑使用
速率限制最适合用于硬性的 API 限制或资源约束。对于 UI 更新或平滑频繁的事件,节流或防抖通常能提供更好的用户体验。
错误处理
该 hook 使用 TanStack Store 进行响应式状态管理。selector 参数允许您指定哪些状态更改会触发重新渲染,通过防止不相关的状态更改导致不必要的重新渲染来优化性能。
默认情况下,不会进行任何响应式状态订阅,您必须通过提供一个 selector 函数来选择启用状态跟踪。这可以防止不必要的重新渲染,并让您完全控制组件何时更新。只有当您提供了一个 selector 时,组件才会根据所选状态值的变化而重新渲染。
可用的状态属性
• 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();
您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。