Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/async-queuer-falsy-items.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/pacer': patch
---

fix(queuer): stop silently dropping falsy items (`0`, `''`, `false`) from AsyncQueuer processing, and stop throwing a TypeError when `null` items are added to AsyncQueuer or Queuer without a custom `getPriority` (fixes #200)
5 changes: 5 additions & 0 deletions .changeset/async-queuer-pending-tick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/pacer': patch
---

fix(async-queuer): respect the `wait` period when `addItem` is called during active processing. `pendingTick` now stays true while executions or wait timers are pending (matching the sync Queuer's semantics), task errors no longer kill the processing chain or produce unhandled promise rejections during tick-driven processing, and `flush`/`flushAsBatch` restart the tick chain they interrupt (fixes #188)
7 changes: 7 additions & 0 deletions .changeset/awaited-return-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tanstack/pacer': patch
'@tanstack/react-pacer': patch
'@tanstack/preact-pacer': patch
---

fix: async utility return types no longer double-wrap promises. `maybeExecute`, `flush`, `lastResult` state, and `onSuccess` callbacks on AsyncDebouncer, AsyncThrottler, and AsyncRateLimiter (and the `asyncDebounce`/`asyncThrottle`/`asyncRateLimit` helpers) now use `Awaited<ReturnType<TFn>>` instead of `ReturnType<TFn>`. The `useAsyncDebouncedCallback`, `useAsyncThrottledCallback`, and `useAsyncRateLimitedCallback` hooks in react-pacer and preact-pacer now return `Promise<Awaited<ReturnType<TFn>> | undefined>`, matching the angular adapter and the actual runtime behavior (fixes #156)
5 changes: 5 additions & 0 deletions .changeset/retryer-key-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/pacer': patch
---

fix: remove the devtools event-client integration from AsyncRetryer to fix unbounded memory growth (#198). Retryer instances are created per-execution by AsyncQueuer, AsyncDebouncer, AsyncThrottler, and AsyncRateLimiter, so every execution permanently accumulated a devtools event listener, a live instance in the devtools registry (keyed `"<key>-retryer-N"`, or `"undefined-retryer-N"` when the parent had no key), and queued devtools events — most visibly as a memory leak in Node.js. The devtools panel never consumed retryer events, so no devtools functionality is lost. The `key` option on AsyncRetryer remains as a plain identifier, and internal retryers now receive `asyncRetryerOptions` unmodified
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Defined in: [angular-pacer/src/async-queuer/injectAsyncQueuedSignal.ts:11](https

Adds an item to the queue. If the queue is full, the item is rejected and onReject is called.
Items can be inserted based on priority or at the front/back depending on configuration.
`undefined` cannot be queued (it is the internal "no item" sentinel) and is always rejected.

#### Parameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ addItem: (item, position?, runOnItemsChange?) => boolean;
Defined in: [angular-pacer/src/queuer/injectQueuedSignal.ts:8](https://github.com/TanStack/pacer/blob/main/packages/angular-pacer/src/queuer/injectQueuedSignal.ts#L8)

Adds an item to the queue. If the queue is full, the item is rejected and onReject is called.
`undefined` cannot be queued (it is the internal "no item" sentinel) and is always rejected.
Items can be inserted based on priority or at the front/back depending on configuration.

Returns true if the item was added, false if the queue is full.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ title: useAsyncDebouncedCallback
# Function: useAsyncDebouncedCallback()

```ts
function useAsyncDebouncedCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncDebouncedCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [preact-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts:44](https://github.com/TanStack/pacer/blob/main/packages/preact-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts#L44)
Defined in: [preact-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts:46](https://github.com/TanStack/pacer/blob/main/packages/preact-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts#L46)

A Preact hook that creates a debounced version of an async callback function.
This hook is a convenient wrapper around the `useAsyncDebouncer` hook,
providing a stable, debounced async function reference for use in Preact components.

The debounced async function will only execute after the specified wait time has elapsed
since its last invocation. If called again before the wait time expires, the timer
resets and starts waiting again. The returned function always returns a promise
that resolves or rejects with the result of the original async function.
resets and starts waiting again. The returned function always returns a promise. The call
that triggers an execution resolves or rejects with that execution's result; superseded
calls resolve with the most recent result (which may be `undefined` if nothing has executed
yet), and calls made while the debouncer is disabled resolve with `undefined`.

This hook provides a simpler API compared to `useAsyncDebouncer`, making it ideal for basic
async debouncing needs. However, it does not expose the underlying AsyncDebouncer instance.
Expand Down Expand Up @@ -50,7 +52,7 @@ Consider using the `useAsyncDebouncer` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -61,7 +63,7 @@ Consider using the `useAsyncDebouncer` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: useAsyncRateLimitedCallback
# Function: useAsyncRateLimitedCallback()

```ts
function useAsyncRateLimitedCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncRateLimitedCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [preact-pacer/src/async-rate-limiter/useAsyncRateLimitedCallback.ts:59](https://github.com/TanStack/pacer/blob/main/packages/preact-pacer/src/async-rate-limiter/useAsyncRateLimitedCallback.ts#L59)
Expand Down Expand Up @@ -64,7 +64,7 @@ Consider using the `useAsyncRateLimiter` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -75,7 +75,7 @@ Consider using the `useAsyncRateLimiter` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ title: useAsyncThrottledCallback
# Function: useAsyncThrottledCallback()

```ts
function useAsyncThrottledCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncThrottledCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [preact-pacer/src/async-throttler/useAsyncThrottledCallback.ts:42](https://github.com/TanStack/pacer/blob/main/packages/preact-pacer/src/async-throttler/useAsyncThrottledCallback.ts#L42)
Defined in: [preact-pacer/src/async-throttler/useAsyncThrottledCallback.ts:43](https://github.com/TanStack/pacer/blob/main/packages/preact-pacer/src/async-throttler/useAsyncThrottledCallback.ts#L43)

A Preact hook that creates a throttled version of an async callback function.
This hook is a convenient wrapper around the `useAsyncThrottler` hook,
providing a stable, throttled async function reference for use in Preact components.

The throttled async function will execute at most once within the specified wait time period,
regardless of how many times it is called. If called multiple times during the wait period,
only the first invocation will execute, and subsequent calls will be ignored until
the wait period has elapsed. The returned function always returns a promise
that resolves or rejects with the result of the original async function.
regardless of how many times it is called. Calls made during the wait period reschedule a
single trailing execution with the latest arguments when `trailing` is enabled (the default).
The most recent call's promise resolves or rejects with the trailing execution's result;
each earlier call's promise resolves immediately with the most recent previous result (or
`undefined` if nothing has executed yet), as does every call when the throttler is disabled.

This hook provides a simpler API compared to `useAsyncThrottler`, making it ideal for basic
async throttling needs. However, it does not expose the underlying AsyncThrottler instance.
Expand Down Expand Up @@ -51,7 +52,7 @@ Consider using the `useAsyncThrottler` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -62,7 +63,7 @@ Consider using the `useAsyncThrottler` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ title: useAsyncDebouncedCallback
# Function: useAsyncDebouncedCallback()

```ts
function useAsyncDebouncedCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncDebouncedCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [react-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts:44](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts#L44)
Defined in: [react-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts:46](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-debouncer/useAsyncDebouncedCallback.ts#L46)

A React hook that creates a debounced version of an async callback function.
This hook is a convenient wrapper around the `useAsyncDebouncer` hook,
providing a stable, debounced async function reference for use in React components.

The debounced async function will only execute after the specified wait time has elapsed
since its last invocation. If called again before the wait time expires, the timer
resets and starts waiting again. The returned function always returns a promise
that resolves or rejects with the result of the original async function.
resets and starts waiting again. The returned function always returns a promise. The call
that triggers an execution resolves or rejects with that execution's result; superseded
calls resolve with the most recent result (which may be `undefined` if nothing has executed
yet), and calls made while the debouncer is disabled resolve with `undefined`.

This hook provides a simpler API compared to `useAsyncDebouncer`, making it ideal for basic
async debouncing needs. However, it does not expose the underlying AsyncDebouncer instance.
Expand Down Expand Up @@ -50,7 +52,7 @@ Consider using the `useAsyncDebouncer` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -61,7 +63,7 @@ Consider using the `useAsyncDebouncer` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: useAsyncRateLimitedCallback
# Function: useAsyncRateLimitedCallback()

```ts
function useAsyncRateLimitedCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncRateLimitedCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [react-pacer/src/async-rate-limiter/useAsyncRateLimitedCallback.ts:59](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-rate-limiter/useAsyncRateLimitedCallback.ts#L59)
Expand Down Expand Up @@ -64,7 +64,7 @@ Consider using the `useAsyncRateLimiter` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -75,7 +75,7 @@ Consider using the `useAsyncRateLimiter` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ title: useAsyncThrottledCallback
# Function: useAsyncThrottledCallback()

```ts
function useAsyncThrottledCallback<TFn>(fn, options): (...args) => Promise<ReturnType<TFn>>;
function useAsyncThrottledCallback<TFn>(fn, options): (...args) => Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [react-pacer/src/async-throttler/useAsyncThrottledCallback.ts:42](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-throttler/useAsyncThrottledCallback.ts#L42)
Defined in: [react-pacer/src/async-throttler/useAsyncThrottledCallback.ts:43](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-throttler/useAsyncThrottledCallback.ts#L43)

A React hook that creates a throttled version of an async callback function.
This hook is a convenient wrapper around the `useAsyncThrottler` hook,
providing a stable, throttled async function reference for use in React components.

The throttled async function will execute at most once within the specified wait time period,
regardless of how many times it is called. If called multiple times during the wait period,
only the first invocation will execute, and subsequent calls will be ignored until
the wait period has elapsed. The returned function always returns a promise
that resolves or rejects with the result of the original async function.
regardless of how many times it is called. Calls made during the wait period reschedule a
single trailing execution with the latest arguments when `trailing` is enabled (the default).
The most recent call's promise resolves or rejects with the trailing execution's result;
each earlier call's promise resolves immediately with the most recent previous result (or
`undefined` if nothing has executed yet), as does every call when the throttler is disabled.

This hook provides a simpler API compared to `useAsyncThrottler`, making it ideal for basic
async throttling needs. However, it does not expose the underlying AsyncThrottler instance.
Expand Down Expand Up @@ -51,7 +52,7 @@ Consider using the `useAsyncThrottler` hook instead.
## Returns

```ts
(...args): Promise<ReturnType<TFn>>;
(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

### Parameters
Expand All @@ -62,7 +63,7 @@ Consider using the `useAsyncThrottler` hook instead.

### Returns

`Promise`\<`ReturnType`\<`TFn`\>\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

## Example

Expand Down
18 changes: 9 additions & 9 deletions docs/reference/classes/AsyncDebouncer.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Defined in: [async-debouncer.ts:219](https://github.com/TanStack/pacer/blob/main
abort(): void;
```

Defined in: [async-debouncer.ts:468](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L468)
Defined in: [async-debouncer.ts:470](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L470)

Aborts all ongoing executions with the internal abort controllers.
Does NOT cancel any pending execution that have not started yet.
Expand All @@ -166,7 +166,7 @@ Does NOT cancel any pending execution that have not started yet.
cancel(): void;
```

Defined in: [async-debouncer.ts:480](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L480)
Defined in: [async-debouncer.ts:482](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L482)

Cancels any pending execution that have not started yet.
Does NOT abort any execution already in progress.
Expand All @@ -180,16 +180,16 @@ Does NOT abort any execution already in progress.
### flush()

```ts
flush(): Promise<ReturnType<TFn> | undefined>;
flush(): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [async-debouncer.ts:403](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L403)
Defined in: [async-debouncer.ts:405](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L405)

Processes the current pending execution immediately

#### Returns

`Promise`\<`ReturnType`\<`TFn`\> \| `undefined`\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

***

Expand All @@ -199,7 +199,7 @@ Processes the current pending execution immediately
getAbortSignal(maybeExecuteCount?): AbortSignal | null;
```

Defined in: [async-debouncer.ts:458](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L458)
Defined in: [async-debouncer.ts:460](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L460)

Returns the AbortSignal for a specific execution.
If no maybeExecuteCount is provided, returns the signal for the most recent execution.
Expand Down Expand Up @@ -237,7 +237,7 @@ const debouncer = new AsyncDebouncer(
### maybeExecute()

```ts
maybeExecute(...args): Promise<ReturnType<TFn> | undefined>;
maybeExecute(...args): Promise<Awaited<ReturnType<TFn>> | undefined>;
```

Defined in: [async-debouncer.ts:317](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L317)
Expand All @@ -260,7 +260,7 @@ Error Handling:

#### Returns

`Promise`\<`ReturnType`\<`TFn`\> \| `undefined`\>
`Promise`\<`Awaited`\<`ReturnType`\<`TFn`\>\> \| `undefined`\>

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

Expand All @@ -276,7 +276,7 @@ The error from the debounced function if no onError handler is configured
reset(): void;
```

Defined in: [async-debouncer.ts:488](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L488)
Defined in: [async-debouncer.ts:490](https://github.com/TanStack/pacer/blob/main/packages/pacer/src/async-debouncer.ts#L490)

Resets the debouncer state to its default values

Expand Down
Loading
Loading