diff --git a/.changeset/blue-lions-bake.md b/.changeset/blue-lions-bake.md new file mode 100644 index 00000000..a87dd7bb --- /dev/null +++ b/.changeset/blue-lions-bake.md @@ -0,0 +1,8 @@ +--- +'@tanstack/pacer-devtools': patch +'@tanstack/react-pacer': patch +'@tanstack/solid-pacer': patch +'@tanstack/pacer': patch +--- + +feat(async-batcher): make result a type parameter diff --git a/docs/framework/react/reference/functions/useasyncbatchedcallback.md b/docs/framework/react/reference/functions/useasyncbatchedcallback.md index e2fbe41e..ec9924bf 100644 --- a/docs/framework/react/reference/functions/useasyncbatchedcallback.md +++ b/docs/framework/react/reference/functions/useasyncbatchedcallback.md @@ -8,10 +8,10 @@ title: useAsyncBatchedCallback # Function: useAsyncBatchedCallback() ```ts -function useAsyncBatchedCallback(fn, options): (...args) => Promise +function useAsyncBatchedCallback(fn, options): (item) => Promise ``` -Defined in: [react-pacer/src/async-batcher/useAsyncBatchedCallback.ts:43](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts#L43) +Defined in: [react-pacer/src/async-batcher/useAsyncBatchedCallback.ts:42](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts#L42) A React hook that creates a batched version of an async callback function. This hook is a convenient wrapper around the `useAsyncBatcher` hook, @@ -34,17 +34,19 @@ Consider using the `useAsyncBatcher` hook instead. ## Type Parameters -• **TFn** *extends* `AnyAsyncFunction` +• **TValue** + +• **TResult** ## Parameters ### fn -(`items`) => `Promise`\<`any`\> +(`items`) => `Promise`\<`TResult`\> ### options -`AsyncBatcherOptions`\<`Parameters`\<`TFn`\>\[`0`\]\> +`AsyncBatcherOptions`\<`TValue`, `TResult`\> ## Returns @@ -52,9 +54,9 @@ Consider using the `useAsyncBatcher` hook instead. ### Parameters -#### args +#### item -...`Parameters`\<`TFn`\> +`TValue` ### Returns diff --git a/docs/framework/react/reference/functions/useasyncbatcher.md b/docs/framework/react/reference/functions/useasyncbatcher.md index c06c3070..8a46d4bb 100644 --- a/docs/framework/react/reference/functions/useasyncbatcher.md +++ b/docs/framework/react/reference/functions/useasyncbatcher.md @@ -8,10 +8,10 @@ title: useAsyncBatcher # Function: useAsyncBatcher() ```ts -function useAsyncBatcher( +function useAsyncBatcher( fn, options, -selector): ReactAsyncBatcher +selector): ReactAsyncBatcher ``` Defined in: [react-pacer/src/async-batcher/useAsyncBatcher.ts:167](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts#L167) @@ -75,17 +75,19 @@ Available state properties: • **TValue** +• **TResult** + • **TSelected** = \{\} ## Parameters ### fn -(`items`) => `Promise`\<`any`\> +(`items`) => `Promise`\<`TResult`\> ### options -`AsyncBatcherOptions`\<`TValue`\> = `{}` +`AsyncBatcherOptions`\<`TValue`, `TResult`\> = `{}` ### selector @@ -93,14 +95,14 @@ Available state properties: ## Returns -[`ReactAsyncBatcher`](../../interfaces/reactasyncbatcher.md)\<`TValue`, `TSelected`\> +[`ReactAsyncBatcher`](../../interfaces/reactasyncbatcher.md)\<`TValue`, `TResult`, `TSelected`\> ## Example ```tsx // Basic async batcher for API requests - no reactive state subscriptions const asyncBatcher = useAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -109,7 +111,7 @@ const asyncBatcher = useAsyncBatcher( // Opt-in to re-render when execution state changes (optimized for loading indicators) const asyncBatcher = useAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -123,7 +125,7 @@ const asyncBatcher = useAsyncBatcher( // Opt-in to re-render when results are available (optimized for data display) const asyncBatcher = useAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -137,7 +139,7 @@ const asyncBatcher = useAsyncBatcher( // Opt-in to re-render when error state changes (optimized for error handling) const asyncBatcher = useAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -155,7 +157,7 @@ const asyncBatcher = useAsyncBatcher( // Complete example with all callbacks const asyncBatcher = useAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, diff --git a/docs/framework/react/reference/interfaces/reactasyncbatcher.md b/docs/framework/react/reference/interfaces/reactasyncbatcher.md index 3b603968..7c2ec716 100644 --- a/docs/framework/react/reference/interfaces/reactasyncbatcher.md +++ b/docs/framework/react/reference/interfaces/reactasyncbatcher.md @@ -5,18 +5,20 @@ title: ReactAsyncBatcher -# Interface: ReactAsyncBatcher\ +# Interface: ReactAsyncBatcher\ Defined in: [react-pacer/src/async-batcher/useAsyncBatcher.ts:10](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts#L10) ## Extends -- `Omit`\<`AsyncBatcher`\<`TValue`\>, `"store"`\> +- `Omit`\<`AsyncBatcher`\<`TValue`, `TResult`\>, `"store"`\> ## Type Parameters • **TValue** +• **TResult** + • **TSelected** = \{\} ## Properties @@ -38,7 +40,7 @@ Use this instead of `batcher.store.state` ### ~~store~~ ```ts -readonly store: Store>>; +readonly store: Store>>; ``` Defined in: [react-pacer/src/async-batcher/useAsyncBatcher.ts:23](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts#L23) diff --git a/docs/framework/solid/reference/functions/createasyncbatcher.md b/docs/framework/solid/reference/functions/createasyncbatcher.md index dc946f8e..df12f637 100644 --- a/docs/framework/solid/reference/functions/createasyncbatcher.md +++ b/docs/framework/solid/reference/functions/createasyncbatcher.md @@ -8,10 +8,10 @@ title: createAsyncBatcher # Function: createAsyncBatcher() ```ts -function createAsyncBatcher( +function createAsyncBatcher( fn, initialOptions, -selector): SolidAsyncBatcher +selector): SolidAsyncBatcher ``` Defined in: [async-batcher/createAsyncBatcher.ts:128](https://github.com/TanStack/pacer/blob/main/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts#L128) @@ -71,7 +71,7 @@ Example usage: ```tsx // Default behavior - no reactive state subscriptions const asyncBatcher = createAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -89,7 +89,7 @@ const asyncBatcher = createAsyncBatcher( // Opt-in to re-render when items or isExecuting changes (optimized for UI updates) const asyncBatcher = createAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -99,7 +99,7 @@ const asyncBatcher = createAsyncBatcher( // Opt-in to re-render when error state changes (optimized for error handling) const asyncBatcher = createAsyncBatcher( - async (items) => { + async (items: Item[]) => { const results = await Promise.all(items.map(item => processItem(item))); return results; }, @@ -121,17 +121,19 @@ const { items, isExecuting } = asyncBatcher.state(); • **TValue** +• **TResult** + • **TSelected** = \{\} ## Parameters ### fn -(`items`) => `Promise`\<`any`\> +(`items`) => `Promise`\<`TResult`\> ### initialOptions -`AsyncBatcherOptions`\<`TValue`\> = `{}` +`AsyncBatcherOptions`\<`TValue`, `TResult`\> = `{}` ### selector @@ -139,4 +141,4 @@ const { items, isExecuting } = asyncBatcher.state(); ## Returns -[`SolidAsyncBatcher`](../../interfaces/solidasyncbatcher.md)\<`TValue`, `TSelected`\> +[`SolidAsyncBatcher`](../../interfaces/solidasyncbatcher.md)\<`TValue`, `TResult`, `TSelected`\> diff --git a/docs/framework/solid/reference/interfaces/solidasyncbatcher.md b/docs/framework/solid/reference/interfaces/solidasyncbatcher.md index 65744f97..dd268338 100644 --- a/docs/framework/solid/reference/interfaces/solidasyncbatcher.md +++ b/docs/framework/solid/reference/interfaces/solidasyncbatcher.md @@ -5,18 +5,20 @@ title: SolidAsyncBatcher -# Interface: SolidAsyncBatcher\ +# Interface: SolidAsyncBatcher\ Defined in: [async-batcher/createAsyncBatcher.ts:10](https://github.com/TanStack/pacer/blob/main/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts#L10) ## Extends -- `Omit`\<`AsyncBatcher`\<`TValue`\>, `"store"`\> +- `Omit`\<`AsyncBatcher`\<`TValue`, `TResult`\>, `"store"`\> ## Type Parameters • **TValue** +• **TResult** + • **TSelected** = \{\} ## Properties @@ -38,7 +40,7 @@ Use this instead of `batcher.store.state` ### ~~store~~ ```ts -readonly store: Store>>; +readonly store: Store>>; ``` Defined in: [async-batcher/createAsyncBatcher.ts:23](https://github.com/TanStack/pacer/blob/main/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts#L23) diff --git a/docs/guides/async-batching.md b/docs/guides/async-batching.md index 233b42c5..440b9eab 100644 --- a/docs/guides/async-batching.md +++ b/docs/guides/async-batching.md @@ -26,8 +26,8 @@ The `asyncBatch` function provides a simple way to create an async batching func ```ts import { asyncBatch } from '@tanstack/pacer' -const processAsyncBatch = asyncBatch( - async (items) => { +const processAsyncBatch = asyncBatch( + async (items: number[]) => { // Process the batch asynchronously const results = await Promise.all( items.map(item => processApiCall(item)) @@ -65,8 +65,8 @@ For more control over async batch behavior, use the `AsyncBatcher` class directl ```ts import { AsyncBatcher } from '@tanstack/pacer' -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { // Process the batch asynchronously const results = await Promise.all( items.map(item => processApiCall(item)) @@ -109,8 +109,8 @@ batcher.start() // Resume processing Unlike the synchronous batcher which returns void, the async version allows you to capture and use the return value from your batch function: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: string[]) => { const results = await processBatch(items) return results }, @@ -130,8 +130,8 @@ const batcher = new AsyncBatcher( The async batcher provides comprehensive error handling capabilities: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { // This might throw an error const results = await riskyBatchOperation(items) return results @@ -164,8 +164,8 @@ const batcher = new AsyncBatcher( The async batcher tracks when batches are actively executing: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { console.log('Starting batch execution...') const results = await longRunningBatchOperation(items) console.log('Batch execution completed') @@ -196,8 +196,8 @@ The `AsyncBatcher` supports these async-specific callbacks: The async batcher provides flexible error handling through the `throwOnError` option: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { // This might throw an error throw new Error('Batch processing failed') }, @@ -222,8 +222,8 @@ const batcher = new AsyncBatcher( Like the synchronous batcher, the async batcher supports dynamic options: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { return await processBatch(items) }, { @@ -360,8 +360,8 @@ The `AsyncBatcherState` includes: The async batcher tracks items that failed during batch processing: ```ts -const batcher = new AsyncBatcher( - async (items) => { +const batcher = new AsyncBatcher( + async (items: number[]) => { // This might fail for some items if (items.some(item => item < 0)) { throw new Error('Negative numbers not allowed') diff --git a/docs/reference/classes/asyncbatcher.md b/docs/reference/classes/asyncbatcher.md index 5a92c897..96be567a 100644 --- a/docs/reference/classes/asyncbatcher.md +++ b/docs/reference/classes/asyncbatcher.md @@ -5,9 +5,9 @@ title: AsyncBatcher -# Class: AsyncBatcher\ +# Class: AsyncBatcher\ -Defined in: [async-batcher.ts:230](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L230) +Defined in: [async-batcher.ts:236](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L236) A class that collects items and processes them in batches asynchronously. @@ -74,39 +74,41 @@ batcher.addItem(2); • **TValue** +• **TResult** + ## Constructors ### new AsyncBatcher() ```ts -new AsyncBatcher(fn, initialOptions): AsyncBatcher +new AsyncBatcher(fn, initialOptions): AsyncBatcher ``` -Defined in: [async-batcher.ts:238](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L238) +Defined in: [async-batcher.ts:243](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L243) #### Parameters ##### fn -(`items`) => `Promise`\<`any`\> +(`items`) => `Promise`\<`TResult`\> ##### initialOptions -[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`\> +[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`, `TResult`\> #### Returns -[`AsyncBatcher`](../asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../asyncbatcher.md)\<`TValue`, `TResult`\> ## Properties ### fn() ```ts -fn: (items) => Promise; +fn: (items) => Promise; ``` -Defined in: [async-batcher.ts:239](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L239) +Defined in: [async-batcher.ts:244](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L244) #### Parameters @@ -116,7 +118,7 @@ Defined in: [async-batcher.ts:239](https://github.com/TanStack/pacer/blob/main/p #### Returns -`Promise`\<`any`\> +`Promise`\<`TResult`\> *** @@ -126,27 +128,27 @@ Defined in: [async-batcher.ts:239](https://github.com/TanStack/pacer/blob/main/p key: string; ``` -Defined in: [async-batcher.ts:234](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L234) +Defined in: [async-batcher.ts:239](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L239) *** ### options ```ts -options: AsyncBatcherOptionsWithOptionalCallbacks; +options: AsyncBatcherOptionsWithOptionalCallbacks; ``` -Defined in: [async-batcher.ts:235](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L235) +Defined in: [async-batcher.ts:240](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L240) *** ### store ```ts -readonly store: Store>>; +readonly store: Store>>; ``` -Defined in: [async-batcher.ts:231](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L231) +Defined in: [async-batcher.ts:237](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L237) ## Methods @@ -156,7 +158,7 @@ Defined in: [async-batcher.ts:231](https://github.com/TanStack/pacer/blob/main/p addItem(item): void ``` -Defined in: [async-batcher.ts:297](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L297) +Defined in: [async-batcher.ts:304](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L304) Adds an item to the async batcher If the batch size is reached, timeout occurs, or shouldProcess returns true, the batch will be processed @@ -179,7 +181,7 @@ If the batch size is reached, timeout occurs, or shouldProcess returns true, the clear(): void ``` -Defined in: [async-batcher.ts:398](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L398) +Defined in: [async-batcher.ts:405](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L405) Removes all items from the async batcher @@ -192,16 +194,16 @@ Removes all items from the async batcher ### flush() ```ts -flush(): Promise +flush(): Promise ``` -Defined in: [async-batcher.ts:372](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L372) +Defined in: [async-batcher.ts:379](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L379) Processes the current batch of items immediately #### Returns -`Promise`\<`any`\> +`Promise`\<`undefined` \| `TResult`\> *** @@ -211,7 +213,7 @@ Processes the current batch of items immediately peekAllItems(): TValue[] ``` -Defined in: [async-batcher.ts:380](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L380) +Defined in: [async-batcher.ts:387](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L387) Returns a copy of all items in the async batcher @@ -227,7 +229,7 @@ Returns a copy of all items in the async batcher peekFailedItems(): TValue[] ``` -Defined in: [async-batcher.ts:384](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L384) +Defined in: [async-batcher.ts:391](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L391) #### Returns @@ -241,7 +243,7 @@ Defined in: [async-batcher.ts:384](https://github.com/TanStack/pacer/blob/main/p reset(): void ``` -Defined in: [async-batcher.ts:405](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L405) +Defined in: [async-batcher.ts:412](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L412) Resets the async batcher state to its default values @@ -257,7 +259,7 @@ Resets the async batcher state to its default values setOptions(newOptions): void ``` -Defined in: [async-batcher.ts:260](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L260) +Defined in: [async-batcher.ts:265](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L265) Updates the async batcher options @@ -265,7 +267,7 @@ Updates the async batcher options ##### newOptions -`Partial`\<[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`\>\> +`Partial`\<[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`, `TResult`\>\> #### Returns diff --git a/docs/reference/functions/asyncbatch.md b/docs/reference/functions/asyncbatch.md index 55a6e9ad..7f71f63d 100644 --- a/docs/reference/functions/asyncbatch.md +++ b/docs/reference/functions/asyncbatch.md @@ -8,10 +8,10 @@ title: asyncBatch # Function: asyncBatch() ```ts -function asyncBatch(fn, options): (item) => void +function asyncBatch(fn, options): (item) => void ``` -Defined in: [async-batcher.ts:460](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L460) +Defined in: [async-batcher.ts:467](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L467) Creates an async batcher that processes items in batches @@ -44,15 +44,17 @@ State Management: • **TValue** +• **TResult** + ## Parameters ### fn -(`items`) => `Promise`\<`any`\> +(`items`) => `Promise`\<`TResult`\> ### options -[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`\> +[`AsyncBatcherOptions`](../../interfaces/asyncbatcheroptions.md)\<`TValue`, `TResult`\> ## Returns @@ -74,8 +76,8 @@ If the batch size is reached, timeout occurs, or shouldProcess returns true, the ## Example ```ts -const batchItems = asyncBatch( - async (items) => { +const batchItems = asyncBatch( + async (items: number[]) => { const result = await processApiCall(items); console.log('Processing:', items); return result; diff --git a/docs/reference/interfaces/asyncbatcheroptions.md b/docs/reference/interfaces/asyncbatcheroptions.md index d8e06dae..87627393 100644 --- a/docs/reference/interfaces/asyncbatcheroptions.md +++ b/docs/reference/interfaces/asyncbatcheroptions.md @@ -5,9 +5,9 @@ title: AsyncBatcherOptions -# Interface: AsyncBatcherOptions\ +# Interface: AsyncBatcherOptions\ -Defined in: [async-batcher.ts:82](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L82) +Defined in: [async-batcher.ts:85](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L85) Options for configuring an AsyncBatcher instance @@ -15,6 +15,8 @@ Options for configuring an AsyncBatcher instance • **TValue** +• **TResult** + ## Properties ### getShouldExecute()? @@ -23,7 +25,7 @@ Options for configuring an AsyncBatcher instance optional getShouldExecute: (items, batcher) => boolean; ``` -Defined in: [async-batcher.ts:87](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L87) +Defined in: [async-batcher.ts:90](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L90) Custom function to determine if a batch should be processed Return true to process the batch immediately @@ -36,7 +38,7 @@ Return true to process the batch immediately ##### batcher -[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`, `TResult`\> #### Returns @@ -47,10 +49,10 @@ Return true to process the batch immediately ### initialState? ```ts -optional initialState: Partial>; +optional initialState: Partial>; ``` -Defined in: [async-batcher.ts:94](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L94) +Defined in: [async-batcher.ts:97](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L97) Initial state for the async batcher @@ -62,7 +64,7 @@ Initial state for the async batcher optional key: string; ``` -Defined in: [async-batcher.ts:99](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L99) +Defined in: [async-batcher.ts:102](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L102) Optional key to identify this async batcher instance. If provided, the async batcher will be identified by this key in the devtools and PacerProvider if applicable. @@ -75,7 +77,7 @@ If provided, the async batcher will be identified by this key in the devtools an optional maxSize: number; ``` -Defined in: [async-batcher.ts:104](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L104) +Defined in: [async-batcher.ts:107](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L107) Maximum number of items in a batch @@ -93,7 +95,7 @@ Infinity optional onError: (error, batch, batcher) => void; ``` -Defined in: [async-batcher.ts:110](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L110) +Defined in: [async-batcher.ts:113](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L113) Optional error handler for when the batch function throws. If provided, the handler will be called with the error, the batch of items that failed, and batcher instance. @@ -111,7 +113,7 @@ This can be used alongside throwOnError - the handler will be called before any ##### batcher -[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`, `TResult`\> #### Returns @@ -125,7 +127,7 @@ This can be used alongside throwOnError - the handler will be called before any optional onItemsChange: (batcher) => void; ``` -Defined in: [async-batcher.ts:118](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L118) +Defined in: [async-batcher.ts:121](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L121) Callback fired after items are added to the batcher @@ -133,7 +135,7 @@ Callback fired after items are added to the batcher ##### batcher -[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`, `TResult`\> #### Returns @@ -147,7 +149,7 @@ Callback fired after items are added to the batcher optional onSettled: (batch, batcher) => void; ``` -Defined in: [async-batcher.ts:122](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L122) +Defined in: [async-batcher.ts:125](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L125) Optional callback to call when a batch is settled (completed or failed) @@ -159,7 +161,7 @@ Optional callback to call when a batch is settled (completed or failed) ##### batcher -[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`, `TResult`\> #### Returns @@ -173,7 +175,7 @@ Optional callback to call when a batch is settled (completed or failed) optional onSuccess: (result, batch, batcher) => void; ``` -Defined in: [async-batcher.ts:126](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L126) +Defined in: [async-batcher.ts:132](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L132) Optional callback to call when a batch succeeds @@ -181,7 +183,7 @@ Optional callback to call when a batch succeeds ##### result -`any` +`TResult` ##### batch @@ -189,7 +191,7 @@ Optional callback to call when a batch succeeds ##### batcher -[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`\> +[`AsyncBatcher`](../../classes/asyncbatcher.md)\<`TValue`, `TResult`\> #### Returns @@ -203,7 +205,7 @@ Optional callback to call when a batch succeeds optional started: boolean; ``` -Defined in: [async-batcher.ts:135](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L135) +Defined in: [async-batcher.ts:141](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L141) Whether the batcher should start processing immediately @@ -221,7 +223,7 @@ true optional throwOnError: boolean; ``` -Defined in: [async-batcher.ts:141](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L141) +Defined in: [async-batcher.ts:147](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L147) Whether to throw errors when they occur. Defaults to true if no onError handler is provided, false if an onError handler is provided. @@ -235,7 +237,7 @@ Can be explicitly set to override these defaults. optional wait: number | (asyncBatcher) => number; ``` -Defined in: [async-batcher.ts:148](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L148) +Defined in: [async-batcher.ts:154](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L154) Maximum time in milliseconds to wait before processing a batch. If the wait duration has elapsed, the batch will be processed. diff --git a/docs/reference/interfaces/asyncbatcherstate.md b/docs/reference/interfaces/asyncbatcherstate.md index 38bbde18..16c72152 100644 --- a/docs/reference/interfaces/asyncbatcherstate.md +++ b/docs/reference/interfaces/asyncbatcherstate.md @@ -5,7 +5,7 @@ title: AsyncBatcherState -# Interface: AsyncBatcherState\ +# Interface: AsyncBatcherState\ Defined in: [async-batcher.ts:6](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L6) @@ -13,6 +13,8 @@ Defined in: [async-batcher.ts:6](https://github.com/TanStack/pacer/blob/main/pac • **TValue** +• **TResult** + ## Properties ### errorCount @@ -90,7 +92,7 @@ Array of items currently queued for batch processing ### lastResult ```ts -lastResult: any; +lastResult: undefined | TResult; ``` Defined in: [async-batcher.ts:34](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-batcher.ts#L34) diff --git a/docs/reference/interfaces/pacereventmap.md b/docs/reference/interfaces/pacereventmap.md index c3b2c862..e7f2b6fb 100644 --- a/docs/reference/interfaces/pacereventmap.md +++ b/docs/reference/interfaces/pacereventmap.md @@ -14,7 +14,7 @@ Defined in: [event-client.ts:13](https://github.com/TanStack/pacer/blob/main/pac ### pacer:AsyncBatcher ```ts -pacer:AsyncBatcher: AsyncBatcher; +pacer:AsyncBatcher: AsyncBatcher; ``` Defined in: [event-client.ts:24](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/event-client.ts#L24) @@ -74,7 +74,7 @@ Defined in: [event-client.ts:29](https://github.com/TanStack/pacer/blob/main/pac ### pacer:d-AsyncBatcher ```ts -pacer:d-AsyncBatcher: AsyncBatcher; +pacer:d-AsyncBatcher: AsyncBatcher; ``` Defined in: [event-client.ts:14](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/event-client.ts#L14) diff --git a/examples/react/asyncBatch/src/index.tsx b/examples/react/asyncBatch/src/index.tsx index be35e2b1..97aa8382 100644 --- a/examples/react/asyncBatch/src/index.tsx +++ b/examples/react/asyncBatch/src/index.tsx @@ -67,7 +67,7 @@ function App() { // Create the async batcher function using useCallback const addToBatch = useCallback( - asyncBatch(processBatch, { + asyncBatch(processBatch, { maxSize: 5, wait: 3000, getShouldExecute: (items) => diff --git a/examples/solid/asyncBatch/src/index.tsx b/examples/solid/asyncBatch/src/index.tsx index 9d6c3435..750fed7c 100644 --- a/examples/solid/asyncBatch/src/index.tsx +++ b/examples/solid/asyncBatch/src/index.tsx @@ -63,7 +63,7 @@ function App() { } // Create the async batcher function - const addToBatch = asyncBatch(processBatch, { + const addToBatch = asyncBatch(processBatch, { maxSize: 5, wait: 3000, getShouldExecute: (items) => diff --git a/packages/pacer-devtools/src/PacerContextProvider.tsx b/packages/pacer-devtools/src/PacerContextProvider.tsx index 8d16fcc4..83e30a06 100644 --- a/packages/pacer-devtools/src/PacerContextProvider.tsx +++ b/packages/pacer-devtools/src/PacerContextProvider.tsx @@ -15,7 +15,7 @@ import type { } from '@tanstack/pacer' interface PacerDevtoolsContextType { - asyncBatchers: Array> + asyncBatchers: Array> asyncDebouncers: Array> asyncQueuers: Array> asyncRateLimiters: Array> diff --git a/packages/pacer/src/async-batcher.ts b/packages/pacer/src/async-batcher.ts index bfc9059f..e6bcf164 100644 --- a/packages/pacer/src/async-batcher.ts +++ b/packages/pacer/src/async-batcher.ts @@ -3,7 +3,7 @@ import { createKey, parseFunctionOrValue } from './utils' import { emitChange, pacerEventClient } from './event-client' import type { OptionalKeys } from './types' -export interface AsyncBatcherState { +export interface AsyncBatcherState { /** * Number of batch executions that have resulted in errors */ @@ -31,7 +31,7 @@ export interface AsyncBatcherState { /** * The result from the most recent batch execution */ - lastResult: any + lastResult: TResult | undefined /** * Number of batch executions that have completed (either successfully or with errors) */ @@ -58,7 +58,10 @@ export interface AsyncBatcherState { totalItemsProcessed: number } -function getDefaultAsyncBatcherState(): AsyncBatcherState { +function getDefaultAsyncBatcherState(): AsyncBatcherState< + TValue, + TResult +> { return { errorCount: 0, failedItems: [], @@ -79,19 +82,19 @@ function getDefaultAsyncBatcherState(): AsyncBatcherState { /** * Options for configuring an AsyncBatcher instance */ -export interface AsyncBatcherOptions { +export interface AsyncBatcherOptions { /** * Custom function to determine if a batch should be processed * Return true to process the batch immediately */ getShouldExecute?: ( items: Array, - batcher: AsyncBatcher, + batcher: AsyncBatcher, ) => boolean /** * Initial state for the async batcher */ - initialState?: Partial> + initialState?: Partial> /** * Optional key to identify this async batcher instance. * If provided, the async batcher will be identified by this key in the devtools and PacerProvider if applicable. @@ -110,23 +113,26 @@ export interface AsyncBatcherOptions { onError?: ( error: unknown, batch: Array, - batcher: AsyncBatcher, + batcher: AsyncBatcher, ) => void /** * Callback fired after items are added to the batcher */ - onItemsChange?: (batcher: AsyncBatcher) => void + onItemsChange?: (batcher: AsyncBatcher) => void /** * Optional callback to call when a batch is settled (completed or failed) */ - onSettled?: (batch: Array, batcher: AsyncBatcher) => void + onSettled?: ( + batch: Array, + batcher: AsyncBatcher, + ) => void /** * Optional callback to call when a batch succeeds */ onSuccess?: ( - result: any, + result: TResult, batch: Array, - batcher: AsyncBatcher, + batcher: AsyncBatcher, ) => void /** * Whether the batcher should start processing immediately @@ -145,11 +151,11 @@ export interface AsyncBatcherOptions { * If not provided, the batch will not be triggered by a timeout. * @default Infinity */ - wait?: number | ((asyncBatcher: AsyncBatcher) => number) + wait?: number | ((asyncBatcher: AsyncBatcher) => number) } -type AsyncBatcherOptionsWithOptionalCallbacks = OptionalKeys< - Required>, +type AsyncBatcherOptionsWithOptionalCallbacks = OptionalKeys< + Required>, | 'initialState' | 'onError' | 'onItemsChange' @@ -158,7 +164,7 @@ type AsyncBatcherOptionsWithOptionalCallbacks = OptionalKeys< | 'key' > -const defaultOptions: AsyncBatcherOptionsWithOptionalCallbacks = { +const defaultOptions: AsyncBatcherOptionsWithOptionalCallbacks = { getShouldExecute: () => false, maxSize: Infinity, started: true, @@ -227,17 +233,16 @@ const defaultOptions: AsyncBatcherOptionsWithOptionalCallbacks = { * // batcher.execute() // manually trigger a batch * ``` */ -export class AsyncBatcher { - readonly store: Store>> = new Store( - getDefaultAsyncBatcherState(), - ) +export class AsyncBatcher { + readonly store: Store>> = + new Store(getDefaultAsyncBatcherState()) key: string - options: AsyncBatcherOptionsWithOptionalCallbacks + options: AsyncBatcherOptionsWithOptionalCallbacks #timeoutId: NodeJS.Timeout | null = null constructor( - public fn: (items: Array) => Promise, - initialOptions: AsyncBatcherOptions, + public fn: (items: Array) => Promise, + initialOptions: AsyncBatcherOptions, ) { this.key = createKey(initialOptions.key) this.options = { @@ -257,11 +262,13 @@ export class AsyncBatcher { /** * Updates the async batcher options */ - setOptions = (newOptions: Partial>): void => { + setOptions = ( + newOptions: Partial>, + ): void => { this.options = { ...this.options, ...newOptions } } - #setState = (newState: Partial>): void => { + #setState = (newState: Partial>): void => { this.store.setState((state) => { const combinedState = { ...state, @@ -325,7 +332,7 @@ export class AsyncBatcher { * @returns A promise that resolves with the result of the batch function, or undefined if an error occurred and was handled by onError * @throws The error from the batch function if no onError handler is configured or throwOnError is true */ - #execute = async (): Promise => { + #execute = async (): Promise => { if (this.store.state.items.length === 0) { return undefined } @@ -369,7 +376,7 @@ export class AsyncBatcher { /** * Processes the current batch of items immediately */ - flush = async (): Promise => { + flush = async (): Promise => { this.#clearTimeout() // clear any pending timeout return await this.#execute() } @@ -403,7 +410,7 @@ export class AsyncBatcher { * Resets the async batcher state to its default values */ reset = (): void => { - this.#setState(getDefaultAsyncBatcherState()) + this.#setState(getDefaultAsyncBatcherState()) this.options.onItemsChange?.(this) } } @@ -438,8 +445,8 @@ export class AsyncBatcher { * * @example * ```ts - * const batchItems = asyncBatch( - * async (items) => { + * const batchItems = asyncBatch( + * async (items: number[]) => { * const result = await processApiCall(items); * console.log('Processing:', items); * return result; @@ -457,10 +464,10 @@ export class AsyncBatcher { * batchItems(3); // Triggers batch processing * ``` */ -export function asyncBatch( - fn: (items: Array) => Promise, - options: AsyncBatcherOptions, +export function asyncBatch( + fn: (items: Array) => Promise, + options: AsyncBatcherOptions, ) { - const batcher = new AsyncBatcher(fn, options) + const batcher = new AsyncBatcher(fn, options) return batcher.addItem } diff --git a/packages/pacer/src/event-client.ts b/packages/pacer/src/event-client.ts index 341cf1f3..22e1656c 100644 --- a/packages/pacer/src/event-client.ts +++ b/packages/pacer/src/event-client.ts @@ -11,7 +11,7 @@ import type { RateLimiter } from './rate-limiter' import type { Throttler } from './throttler' export interface PacerEventMap { - 'pacer:d-AsyncBatcher': AsyncBatcher + 'pacer:d-AsyncBatcher': AsyncBatcher 'pacer:d-AsyncDebouncer': AsyncDebouncer 'pacer:d-AsyncQueuer': AsyncQueuer 'pacer:d-AsyncRateLimiter': AsyncRateLimiter @@ -21,7 +21,7 @@ export interface PacerEventMap { 'pacer:d-Queuer': Queuer 'pacer:d-RateLimiter': RateLimiter 'pacer:d-Throttler': Throttler - 'pacer:AsyncBatcher': AsyncBatcher + 'pacer:AsyncBatcher': AsyncBatcher 'pacer:AsyncDebouncer': AsyncDebouncer 'pacer:AsyncQueuer': AsyncQueuer 'pacer:AsyncRateLimiter': AsyncRateLimiter diff --git a/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts b/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts index 041aa472..e43c504b 100644 --- a/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts +++ b/packages/react-pacer/src/async-batcher/useAsyncBatchedCallback.ts @@ -1,7 +1,6 @@ import { useCallback } from 'react' import { useAsyncBatcher } from './useAsyncBatcher' import type { AsyncBatcherOptions } from '@tanstack/pacer/async-batcher' -import type { AnyAsyncFunction } from '@tanstack/pacer/types' /** * A React hook that creates a batched version of an async callback function. @@ -40,14 +39,14 @@ import type { AnyAsyncFunction } from '@tanstack/pacer/types' * * ``` */ -export function useAsyncBatchedCallback( - fn: (items: Array[0]>) => Promise, - options: AsyncBatcherOptions[0]>, -): (...args: Parameters) => Promise { +export function useAsyncBatchedCallback( + fn: (items: Array) => Promise, + options: AsyncBatcherOptions, +): (item: TValue) => Promise { const asyncBatchedFn = useAsyncBatcher(fn, options).addItem return useCallback( - async (...args) => { - asyncBatchedFn(args[0]) + async (item: TValue) => { + asyncBatchedFn(item) }, [asyncBatchedFn], ) diff --git a/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts b/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts index ec9aa342..b37ce688 100644 --- a/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts +++ b/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts @@ -7,8 +7,8 @@ import type { AsyncBatcherState, } from '@tanstack/pacer/async-batcher' -export interface ReactAsyncBatcher - extends Omit, 'store'> { +export interface ReactAsyncBatcher + extends Omit, 'store'> { /** * Reactive state that will be updated and re-rendered when the batcher state changes * @@ -20,7 +20,7 @@ export interface ReactAsyncBatcher * The state on the store object is not reactive, as it has not been wrapped in a `useStore` hook internally. * Although, you can make the state reactive by using the `useStore` in your own usage. */ - readonly store: Store>> + readonly store: Store>> } /** @@ -83,7 +83,7 @@ export interface ReactAsyncBatcher * ```tsx * // Basic async batcher for API requests - no reactive state subscriptions * const asyncBatcher = useAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -92,7 +92,7 @@ export interface ReactAsyncBatcher * * // Opt-in to re-render when execution state changes (optimized for loading indicators) * const asyncBatcher = useAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -106,7 +106,7 @@ export interface ReactAsyncBatcher * * // Opt-in to re-render when results are available (optimized for data display) * const asyncBatcher = useAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -120,7 +120,7 @@ export interface ReactAsyncBatcher * * // Opt-in to re-render when error state changes (optimized for error handling) * const asyncBatcher = useAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -138,7 +138,7 @@ export interface ReactAsyncBatcher * * // Complete example with all callbacks * const asyncBatcher = useAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -164,13 +164,15 @@ export interface ReactAsyncBatcher * const { isExecuting, lastResult, size } = asyncBatcher.state; * ``` */ -export function useAsyncBatcher( - fn: (items: Array) => Promise, - options: AsyncBatcherOptions = {}, - selector: (state: AsyncBatcherState) => TSelected = () => +export function useAsyncBatcher( + fn: (items: Array) => Promise, + options: AsyncBatcherOptions = {}, + selector: (state: AsyncBatcherState) => TSelected = () => ({}) as TSelected, -): ReactAsyncBatcher { - const [asyncBatcher] = useState(() => new AsyncBatcher(fn, options)) +): ReactAsyncBatcher { + const [asyncBatcher] = useState( + () => new AsyncBatcher(fn, options), + ) const state = useStore(asyncBatcher.store, selector) @@ -182,7 +184,7 @@ export function useAsyncBatcher( ({ ...asyncBatcher, state, - }) as ReactAsyncBatcher, // omit `store` in favor of `state` + }) as ReactAsyncBatcher, // omit `store` in favor of `state` [asyncBatcher, state], ) } diff --git a/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts b/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts index 3d26a741..9c587b30 100644 --- a/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts +++ b/packages/solid-pacer/src/async-batcher/createAsyncBatcher.ts @@ -7,8 +7,8 @@ import type { AsyncBatcherState, } from '@tanstack/pacer/async-batcher' -export interface SolidAsyncBatcher - extends Omit, 'store'> { +export interface SolidAsyncBatcher + extends Omit, 'store'> { /** * Reactive state that will be updated when the batcher state changes * @@ -20,7 +20,7 @@ export interface SolidAsyncBatcher * The state on the store object is not reactive, as it has not been wrapped in a `useStore` hook internally. * Although, you can make the state reactive by using the `useStore` in your own usage. */ - readonly store: Store>> + readonly store: Store>> } /** @@ -79,7 +79,7 @@ export interface SolidAsyncBatcher * ```tsx * // Default behavior - no reactive state subscriptions * const asyncBatcher = createAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -97,7 +97,7 @@ export interface SolidAsyncBatcher * * // Opt-in to re-render when items or isExecuting changes (optimized for UI updates) * const asyncBatcher = createAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -107,7 +107,7 @@ export interface SolidAsyncBatcher * * // Opt-in to re-render when error state changes (optimized for error handling) * const asyncBatcher = createAsyncBatcher( - * async (items) => { + * async (items: Item[]) => { * const results = await Promise.all(items.map(item => processItem(item))); * return results; * }, @@ -125,18 +125,18 @@ export interface SolidAsyncBatcher * const { items, isExecuting } = asyncBatcher.state(); * ``` */ -export function createAsyncBatcher( - fn: (items: Array) => Promise, - initialOptions: AsyncBatcherOptions = {}, - selector: (state: AsyncBatcherState) => TSelected = () => +export function createAsyncBatcher( + fn: (items: Array) => Promise, + initialOptions: AsyncBatcherOptions = {}, + selector: (state: AsyncBatcherState) => TSelected = () => ({}) as TSelected, -): SolidAsyncBatcher { - const asyncBatcher = new AsyncBatcher(fn, initialOptions) +): SolidAsyncBatcher { + const asyncBatcher = new AsyncBatcher(fn, initialOptions) const state = useStore(asyncBatcher.store, selector) return { ...asyncBatcher, state, - } as SolidAsyncBatcher // omit `store` in favor of `state` + } as SolidAsyncBatcher // omit `store` in favor of `state` }