@tanstack/solid-pacer 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/async-debouncer/createAsyncDebouncer.cjs +22 -7
- package/dist/cjs/async-debouncer/createAsyncDebouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer/createAsyncDebouncer.d.cts +6 -3
- package/dist/cjs/async-queuer/createAsyncQueuer.cjs.map +1 -1
- package/dist/cjs/async-queuer/createAsyncQueuer.d.cts +5 -1
- package/dist/cjs/async-rate-limiter/createAsyncRateLimiter.cjs +20 -9
- package/dist/cjs/async-rate-limiter/createAsyncRateLimiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter/createAsyncRateLimiter.d.cts +5 -3
- package/dist/cjs/async-throttler/createAsyncThrottler.cjs +32 -10
- package/dist/cjs/async-throttler/createAsyncThrottler.cjs.map +1 -1
- package/dist/cjs/async-throttler/createAsyncThrottler.d.cts +7 -3
- package/dist/cjs/debouncer/createDebouncedSignal.cjs.map +1 -1
- package/dist/cjs/debouncer/createDebouncedSignal.d.cts +1 -5
- package/dist/cjs/debouncer/createDebouncedValue.cjs +0 -3
- package/dist/cjs/debouncer/createDebouncedValue.cjs.map +1 -1
- package/dist/cjs/debouncer/createDebouncedValue.d.cts +5 -11
- package/dist/cjs/debouncer/createDebouncer.cjs +7 -2
- package/dist/cjs/debouncer/createDebouncer.cjs.map +1 -1
- package/dist/cjs/debouncer/createDebouncer.d.cts +2 -2
- package/dist/cjs/queuer/createQueuer.cjs +2 -2
- package/dist/cjs/queuer/createQueuer.cjs.map +1 -1
- package/dist/cjs/queuer/createQueuer.d.cts +4 -0
- package/dist/cjs/rate-limiter/createRateLimitedSignal.cjs.map +1 -1
- package/dist/cjs/rate-limiter/createRateLimitedSignal.d.cts +1 -5
- package/dist/cjs/rate-limiter/createRateLimitedValue.cjs.map +1 -1
- package/dist/cjs/rate-limiter/createRateLimitedValue.d.cts +9 -20
- package/dist/cjs/rate-limiter/createRateLimiter.cjs +4 -2
- package/dist/cjs/rate-limiter/createRateLimiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter/createRateLimiter.d.cts +2 -2
- package/dist/cjs/throttler/createThrottledSignal.cjs.map +1 -1
- package/dist/cjs/throttler/createThrottledSignal.d.cts +1 -5
- package/dist/cjs/throttler/createThrottledValue.cjs +0 -3
- package/dist/cjs/throttler/createThrottledValue.cjs.map +1 -1
- package/dist/cjs/throttler/createThrottledValue.d.cts +10 -14
- package/dist/cjs/throttler/createThrottler.cjs +7 -2
- package/dist/cjs/throttler/createThrottler.cjs.map +1 -1
- package/dist/cjs/throttler/createThrottler.d.cts +2 -2
- package/dist/esm/async-debouncer/createAsyncDebouncer.d.ts +6 -3
- package/dist/esm/async-debouncer/createAsyncDebouncer.js +22 -7
- package/dist/esm/async-debouncer/createAsyncDebouncer.js.map +1 -1
- package/dist/esm/async-queuer/createAsyncQueuer.d.ts +5 -1
- package/dist/esm/async-queuer/createAsyncQueuer.js.map +1 -1
- package/dist/esm/async-rate-limiter/createAsyncRateLimiter.d.ts +5 -3
- package/dist/esm/async-rate-limiter/createAsyncRateLimiter.js +20 -9
- package/dist/esm/async-rate-limiter/createAsyncRateLimiter.js.map +1 -1
- package/dist/esm/async-throttler/createAsyncThrottler.d.ts +7 -3
- package/dist/esm/async-throttler/createAsyncThrottler.js +32 -10
- package/dist/esm/async-throttler/createAsyncThrottler.js.map +1 -1
- package/dist/esm/debouncer/createDebouncedSignal.d.ts +1 -5
- package/dist/esm/debouncer/createDebouncedSignal.js.map +1 -1
- package/dist/esm/debouncer/createDebouncedValue.d.ts +5 -11
- package/dist/esm/debouncer/createDebouncedValue.js +1 -4
- package/dist/esm/debouncer/createDebouncedValue.js.map +1 -1
- package/dist/esm/debouncer/createDebouncer.d.ts +2 -2
- package/dist/esm/debouncer/createDebouncer.js +8 -3
- package/dist/esm/debouncer/createDebouncer.js.map +1 -1
- package/dist/esm/queuer/createQueuer.d.ts +4 -0
- package/dist/esm/queuer/createQueuer.js +2 -2
- package/dist/esm/queuer/createQueuer.js.map +1 -1
- package/dist/esm/rate-limiter/createRateLimitedSignal.d.ts +1 -5
- package/dist/esm/rate-limiter/createRateLimitedSignal.js.map +1 -1
- package/dist/esm/rate-limiter/createRateLimitedValue.d.ts +9 -20
- package/dist/esm/rate-limiter/createRateLimitedValue.js.map +1 -1
- package/dist/esm/rate-limiter/createRateLimiter.d.ts +2 -2
- package/dist/esm/rate-limiter/createRateLimiter.js +4 -2
- package/dist/esm/rate-limiter/createRateLimiter.js.map +1 -1
- package/dist/esm/throttler/createThrottledSignal.d.ts +1 -5
- package/dist/esm/throttler/createThrottledSignal.js.map +1 -1
- package/dist/esm/throttler/createThrottledValue.d.ts +10 -14
- package/dist/esm/throttler/createThrottledValue.js +1 -4
- package/dist/esm/throttler/createThrottledValue.js.map +1 -1
- package/dist/esm/throttler/createThrottler.d.ts +2 -2
- package/dist/esm/throttler/createThrottler.js +8 -3
- package/dist/esm/throttler/createThrottler.js.map +1 -1
- package/package.json +2 -2
- package/src/async-debouncer/createAsyncDebouncer.ts +40 -24
- package/src/async-queuer/createAsyncQueuer.ts +6 -2
- package/src/async-rate-limiter/createAsyncRateLimiter.ts +34 -26
- package/src/async-throttler/createAsyncThrottler.ts +49 -24
- package/src/debouncer/createDebouncedSignal.ts +2 -6
- package/src/debouncer/createDebouncedValue.ts +7 -16
- package/src/debouncer/createDebouncer.ts +16 -15
- package/src/queuer/createQueuer.ts +7 -3
- package/src/rate-limiter/createRateLimitedSignal.ts +2 -6
- package/src/rate-limiter/createRateLimitedValue.ts +10 -21
- package/src/rate-limiter/createRateLimiter.ts +14 -15
- package/src/throttler/createThrottledSignal.ts +2 -6
- package/src/throttler/createThrottledValue.ts +12 -19
- package/src/throttler/createThrottler.ts +17 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createThrottledValue.js","sources":["../../../src/throttler/createThrottledValue.ts"],"sourcesContent":["import { createEffect
|
|
1
|
+
{"version":3,"file":"createThrottledValue.js","sources":["../../../src/throttler/createThrottledValue.ts"],"sourcesContent":["import { createEffect } from 'solid-js'\nimport { createThrottledSignal } from './createThrottledSignal'\nimport type { SolidThrottler } from './createThrottler'\nimport type { Accessor, Setter } from 'solid-js'\nimport type { ThrottlerOptions } from '@tanstack/pacer/throttler'\n\n/**\n * A high-level Solid hook that creates a throttled version of a value that updates at most once within a specified time window.\n * This hook uses Solid's createSignal internally to manage the throttled state.\n *\n * Throttling ensures the value updates occur at a controlled rate regardless of how frequently the input value changes.\n * This is useful for rate-limiting expensive re-renders or API calls that depend on rapidly changing values.\n *\n * The hook returns a tuple containing:\n * - An accessor function that provides the throttled value\n * - The throttler instance with control methods\n *\n * The throttled value will update according to the leading/trailing edge behavior specified in the options.\n *\n * For more direct control over throttling behavior without Solid state management,\n * consider using the lower-level createThrottler hook instead.\n *\n * @example\n * ```tsx\n * // Basic throttling - update at most once per second\n * const [throttledValue, throttler] = createThrottledValue(rawValue, { wait: 1000 });\n *\n * // Use the throttled value\n * console.log(throttledValue()); // Access the current throttled value\n *\n * // Control the throttler\n * throttler.cancel(); // Cancel any pending updates\n * ```\n */\nexport function createThrottledValue<TValue>(\n value: Accessor<TValue>,\n initialOptions: ThrottlerOptions<Setter<TValue>>,\n): [Accessor<TValue>, SolidThrottler<Setter<TValue>>] {\n const [throttledValue, setThrottledValue, throttler] = createThrottledSignal(\n value(),\n initialOptions,\n )\n\n createEffect(() => {\n setThrottledValue(value() as any)\n })\n\n return [throttledValue, throttler]\n}\n"],"names":[],"mappings":";;AAkCgB,SAAA,qBACd,OACA,gBACoD;AACpD,QAAM,CAAC,gBAAgB,mBAAmB,SAAS,IAAI;AAAA,IACrD,MAAM;AAAA,IACN;AAAA,EACF;AAEA,eAAa,MAAM;AACjB,sBAAkB,OAAc;AAAA,EAAA,CACjC;AAEM,SAAA,CAAC,gBAAgB,SAAS;AACnC;"}
|
|
@@ -4,7 +4,7 @@ import { AnyFunction } from '@tanstack/pacer/types';
|
|
|
4
4
|
/**
|
|
5
5
|
* An extension of the Throttler class that adds Solid signals to access the internal state of the throttler
|
|
6
6
|
*/
|
|
7
|
-
export interface SolidThrottler<TFn extends AnyFunction
|
|
7
|
+
export interface SolidThrottler<TFn extends AnyFunction> extends Omit<Throttler<TFn>, 'getExecutionCount' | 'getIsPending' | 'getLastExecutionTime' | 'getNextExecutionTime'> {
|
|
8
8
|
executionCount: Accessor<number>;
|
|
9
9
|
isPending: Accessor<boolean>;
|
|
10
10
|
lastExecutionTime: Accessor<number>;
|
|
@@ -44,4 +44,4 @@ export interface SolidThrottler<TFn extends AnyFunction, TArgs extends Parameter
|
|
|
44
44
|
* console.log(throttler.nextExecutionTime()); // timestamp of next allowed execution
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
|
-
export declare function createThrottler<TFn extends AnyFunction
|
|
47
|
+
export declare function createThrottler<TFn extends AnyFunction>(fn: TFn, initialOptions: ThrottlerOptions<TFn>): SolidThrottler<TFn>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Throttler } from "@tanstack/pacer/throttler";
|
|
2
|
-
import { createSignal } from "solid-js";
|
|
2
|
+
import { createSignal, createEffect, onCleanup } from "solid-js";
|
|
3
3
|
import { bindInstanceMethods } from "@tanstack/pacer/utils";
|
|
4
4
|
function createThrottler(fn, initialOptions) {
|
|
5
|
-
const throttler = new Throttler(fn, initialOptions);
|
|
5
|
+
const throttler = bindInstanceMethods(new Throttler(fn, initialOptions));
|
|
6
6
|
const [executionCount, setExecutionCount] = createSignal(
|
|
7
7
|
throttler.getExecutionCount()
|
|
8
8
|
);
|
|
@@ -27,8 +27,13 @@ function createThrottler(fn, initialOptions) {
|
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
setOptions(initialOptions);
|
|
30
|
+
createEffect(() => {
|
|
31
|
+
onCleanup(() => {
|
|
32
|
+
throttler.cancel();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
30
35
|
return {
|
|
31
|
-
...
|
|
36
|
+
...throttler,
|
|
32
37
|
executionCount,
|
|
33
38
|
isPending,
|
|
34
39
|
lastExecutionTime,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createThrottler.js","sources":["../../../src/throttler/createThrottler.ts"],"sourcesContent":["import { Throttler } from '@tanstack/pacer/throttler'\nimport { createSignal } from 'solid-js'\nimport { bindInstanceMethods } from '@tanstack/pacer/utils'\nimport type { Accessor } from 'solid-js'\nimport type { AnyFunction } from '@tanstack/pacer/types'\nimport type { ThrottlerOptions } from '@tanstack/pacer/throttler'\n\n/**\n * An extension of the Throttler class that adds Solid signals to access the internal state of the throttler\n */\nexport interface SolidThrottler
|
|
1
|
+
{"version":3,"file":"createThrottler.js","sources":["../../../src/throttler/createThrottler.ts"],"sourcesContent":["import { Throttler } from '@tanstack/pacer/throttler'\nimport { createEffect, createSignal, onCleanup } from 'solid-js'\nimport { bindInstanceMethods } from '@tanstack/pacer/utils'\nimport type { Accessor } from 'solid-js'\nimport type { AnyFunction } from '@tanstack/pacer/types'\nimport type { ThrottlerOptions } from '@tanstack/pacer/throttler'\n\n/**\n * An extension of the Throttler class that adds Solid signals to access the internal state of the throttler\n */\nexport interface SolidThrottler<TFn extends AnyFunction>\n extends Omit<\n Throttler<TFn>,\n | 'getExecutionCount'\n | 'getIsPending'\n | 'getLastExecutionTime'\n | 'getNextExecutionTime'\n > {\n executionCount: Accessor<number>\n isPending: Accessor<boolean>\n lastExecutionTime: Accessor<number>\n nextExecutionTime: Accessor<number>\n}\n\n/**\n * A low-level Solid hook that creates a `Throttler` instance that limits how often the provided function can execute.\n *\n * This hook is designed to be flexible and state-management agnostic - it simply returns a throttler instance that\n * you can integrate with any state management solution (createSignal, Redux, Zustand, Jotai, etc). For a simpler and higher-level hook that\n * integrates directly with Solid's createSignal, see createThrottledSignal.\n *\n * Throttling ensures a function executes at most once within a specified time window,\n * regardless of how many times it is called. This is useful for rate-limiting\n * expensive operations or UI updates.\n *\n * @example\n * ```tsx\n * // Basic throttling with custom state\n * const [value, setValue] = createSignal(0);\n * const throttler = createThrottler(setValue, { wait: 1000 });\n *\n * // With any state manager\n * const throttler = createThrottler(\n * (value) => stateManager.setState(value),\n * {\n * wait: 2000,\n * leading: true, // Execute immediately on first call\n * trailing: false // Skip trailing edge updates\n * }\n * );\n *\n * // Access throttler state via signals\n * console.log(throttler.executionCount()); // number of times executed\n * console.log(throttler.isPending()); // whether throttled function is pending\n * console.log(throttler.lastExecutionTime()); // timestamp of last execution\n * console.log(throttler.nextExecutionTime()); // timestamp of next allowed execution\n * ```\n */\nexport function createThrottler<TFn extends AnyFunction>(\n fn: TFn,\n initialOptions: ThrottlerOptions<TFn>,\n): SolidThrottler<TFn> {\n const throttler = bindInstanceMethods(new Throttler<TFn>(fn, initialOptions))\n\n const [executionCount, setExecutionCount] = createSignal(\n throttler.getExecutionCount(),\n )\n const [isPending, setIsPending] = createSignal(throttler.getIsPending())\n const [lastExecutionTime, setLastExecutionTime] = createSignal(\n throttler.getLastExecutionTime(),\n )\n const [nextExecutionTime, setNextExecutionTime] = createSignal(\n throttler.getNextExecutionTime(),\n )\n\n function setOptions(newOptions: Partial<ThrottlerOptions<TFn>>) {\n throttler.setOptions({\n ...newOptions,\n onExecute: (throttler) => {\n setExecutionCount(throttler.getExecutionCount())\n setIsPending(throttler.getIsPending())\n setLastExecutionTime(throttler.getLastExecutionTime())\n setNextExecutionTime(throttler.getNextExecutionTime())\n\n const onExecute = newOptions.onExecute ?? initialOptions.onExecute\n onExecute?.(throttler)\n },\n })\n }\n\n setOptions(initialOptions)\n\n createEffect(() => {\n onCleanup(() => {\n throttler.cancel()\n })\n })\n\n return {\n ...throttler,\n executionCount,\n isPending,\n lastExecutionTime,\n nextExecutionTime,\n setOptions,\n } as SolidThrottler<TFn>\n}\n"],"names":["throttler"],"mappings":";;;AA0DgB,SAAA,gBACd,IACA,gBACqB;AACrB,QAAM,YAAY,oBAAoB,IAAI,UAAe,IAAI,cAAc,CAAC;AAEtE,QAAA,CAAC,gBAAgB,iBAAiB,IAAI;AAAA,IAC1C,UAAU,kBAAkB;AAAA,EAC9B;AACA,QAAM,CAAC,WAAW,YAAY,IAAI,aAAa,UAAU,cAAc;AACjE,QAAA,CAAC,mBAAmB,oBAAoB,IAAI;AAAA,IAChD,UAAU,qBAAqB;AAAA,EACjC;AACM,QAAA,CAAC,mBAAmB,oBAAoB,IAAI;AAAA,IAChD,UAAU,qBAAqB;AAAA,EACjC;AAEA,WAAS,WAAW,YAA4C;AAC9D,cAAU,WAAW;AAAA,MACnB,GAAG;AAAA,MACH,WAAW,CAACA,eAAc;AACNA,0BAAAA,WAAU,mBAAmB;AAClCA,qBAAAA,WAAU,cAAc;AAChBA,6BAAAA,WAAU,sBAAsB;AAChCA,6BAAAA,WAAU,sBAAsB;AAE/C,cAAA,YAAY,WAAW,aAAa,eAAe;AACzD,+CAAYA;AAAAA,MAAS;AAAA,IACvB,CACD;AAAA,EAAA;AAGH,aAAW,cAAc;AAEzB,eAAa,MAAM;AACjB,cAAU,MAAM;AACd,gBAAU,OAAO;AAAA,IAAA,CAClB;AAAA,EAAA,CACF;AAEM,SAAA;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/solid-pacer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Utilities for debouncing and throttling functions in Solid.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"src"
|
|
143
143
|
],
|
|
144
144
|
"dependencies": {
|
|
145
|
-
"@tanstack/pacer": "0.
|
|
145
|
+
"@tanstack/pacer": "0.3.0"
|
|
146
146
|
},
|
|
147
147
|
"devDependencies": {
|
|
148
148
|
"solid-js": "^1.9.5",
|
|
@@ -5,15 +5,20 @@ import type { AsyncDebouncerOptions } from '@tanstack/pacer/async-debouncer'
|
|
|
5
5
|
import type { AnyAsyncFunction } from '@tanstack/pacer/types'
|
|
6
6
|
import type { Accessor } from 'solid-js'
|
|
7
7
|
|
|
8
|
-
export interface SolidAsyncDebouncer<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export interface SolidAsyncDebouncer<TFn extends AnyAsyncFunction>
|
|
9
|
+
extends Omit<
|
|
10
|
+
AsyncDebouncer<TFn>,
|
|
11
|
+
| 'getErrorCount'
|
|
12
|
+
| 'getIsPending'
|
|
13
|
+
| 'getLastResult'
|
|
14
|
+
| 'getSettleCount'
|
|
15
|
+
| 'getSuccessCount'
|
|
14
16
|
> {
|
|
15
|
-
|
|
17
|
+
errorCount: Accessor<number>
|
|
16
18
|
isPending: Accessor<boolean>
|
|
19
|
+
lastResult: Accessor<ReturnType<TFn> | undefined>
|
|
20
|
+
settleCount: Accessor<number>
|
|
21
|
+
successCount: Accessor<number>
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
/**
|
|
@@ -51,29 +56,37 @@ export interface SolidAsyncDebouncer<
|
|
|
51
56
|
* ```
|
|
52
57
|
*/
|
|
53
58
|
|
|
54
|
-
export function createAsyncDebouncer<
|
|
55
|
-
TFn extends AnyAsyncFunction,
|
|
56
|
-
TArgs extends Parameters<TFn>,
|
|
57
|
-
>(
|
|
59
|
+
export function createAsyncDebouncer<TFn extends AnyAsyncFunction>(
|
|
58
60
|
fn: TFn,
|
|
59
|
-
initialOptions: AsyncDebouncerOptions<TFn
|
|
60
|
-
): SolidAsyncDebouncer<TFn
|
|
61
|
-
const asyncDebouncer = new AsyncDebouncer<TFn
|
|
61
|
+
initialOptions: AsyncDebouncerOptions<TFn>,
|
|
62
|
+
): SolidAsyncDebouncer<TFn> {
|
|
63
|
+
const asyncDebouncer = new AsyncDebouncer<TFn>(fn, initialOptions)
|
|
62
64
|
|
|
63
|
-
const [
|
|
64
|
-
asyncDebouncer.
|
|
65
|
+
const [errorCount, setErrorCount] = createSignal(
|
|
66
|
+
asyncDebouncer.getErrorCount(),
|
|
67
|
+
)
|
|
68
|
+
const [settleCount, setSettleCount] = createSignal(
|
|
69
|
+
asyncDebouncer.getSettleCount(),
|
|
70
|
+
)
|
|
71
|
+
const [successCount, setSuccessCount] = createSignal(
|
|
72
|
+
asyncDebouncer.getSuccessCount(),
|
|
65
73
|
)
|
|
66
74
|
const [isPending, setIsPending] = createSignal(asyncDebouncer.getIsPending())
|
|
75
|
+
const [lastResult, setLastResult] = createSignal(
|
|
76
|
+
asyncDebouncer.getLastResult(),
|
|
77
|
+
)
|
|
67
78
|
|
|
68
|
-
function setOptions(newOptions: Partial<AsyncDebouncerOptions<TFn
|
|
79
|
+
function setOptions(newOptions: Partial<AsyncDebouncerOptions<TFn>>) {
|
|
69
80
|
asyncDebouncer.setOptions({
|
|
70
81
|
...newOptions,
|
|
71
|
-
|
|
72
|
-
|
|
82
|
+
onSettled: (asyncDebouncer) => {
|
|
83
|
+
setSuccessCount(asyncDebouncer.getSuccessCount())
|
|
84
|
+
setErrorCount(asyncDebouncer.getErrorCount())
|
|
85
|
+
setSettleCount(asyncDebouncer.getSettleCount())
|
|
73
86
|
setIsPending(asyncDebouncer.getIsPending())
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
87
|
+
setLastResult(asyncDebouncer.getLastResult())
|
|
88
|
+
const onSettled = newOptions.onSettled ?? initialOptions.onSettled
|
|
89
|
+
onSettled?.(asyncDebouncer)
|
|
77
90
|
},
|
|
78
91
|
})
|
|
79
92
|
}
|
|
@@ -82,8 +95,11 @@ export function createAsyncDebouncer<
|
|
|
82
95
|
|
|
83
96
|
return {
|
|
84
97
|
...bindInstanceMethods(asyncDebouncer),
|
|
85
|
-
|
|
98
|
+
errorCount,
|
|
86
99
|
isPending,
|
|
100
|
+
lastResult,
|
|
101
|
+
settleCount,
|
|
102
|
+
successCount,
|
|
87
103
|
setOptions,
|
|
88
|
-
}
|
|
104
|
+
} as SolidAsyncDebouncer<TFn>
|
|
89
105
|
}
|
|
@@ -49,11 +49,15 @@ export interface SolidAsyncQueuer<TValue>
|
|
|
49
49
|
/**
|
|
50
50
|
* Signal version of `getPeek`
|
|
51
51
|
*/
|
|
52
|
-
peek: Accessor<TValue | undefined>
|
|
52
|
+
peek: Accessor<(() => Promise<TValue>) | undefined>
|
|
53
53
|
/**
|
|
54
54
|
* Signal version of `getPendingItems`
|
|
55
55
|
*/
|
|
56
56
|
pendingItems: Accessor<Array<() => Promise<TValue>>>
|
|
57
|
+
/**
|
|
58
|
+
* Signal version of `getRejectionCount`
|
|
59
|
+
*/
|
|
60
|
+
rejectionCount: Accessor<number>
|
|
57
61
|
/**
|
|
58
62
|
* Signal version of `getSize`
|
|
59
63
|
*/
|
|
@@ -171,5 +175,5 @@ export function createAsyncQueuer<TValue>(
|
|
|
171
175
|
pendingItems,
|
|
172
176
|
rejectionCount,
|
|
173
177
|
size,
|
|
174
|
-
}
|
|
178
|
+
} as SolidAsyncQueuer<TValue>
|
|
175
179
|
}
|
|
@@ -5,17 +5,19 @@ import type { Accessor } from 'solid-js'
|
|
|
5
5
|
import type { AnyAsyncFunction } from '@tanstack/pacer/types'
|
|
6
6
|
import type { AsyncRateLimiterOptions } from '@tanstack/pacer/async-rate-limiter'
|
|
7
7
|
|
|
8
|
-
export interface SolidAsyncRateLimiter<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
| '
|
|
8
|
+
export interface SolidAsyncRateLimiter<TFn extends AnyAsyncFunction>
|
|
9
|
+
extends Omit<
|
|
10
|
+
AsyncRateLimiter<TFn>,
|
|
11
|
+
| 'getSuccessCount'
|
|
12
|
+
| 'getSettleCount'
|
|
13
|
+
| 'getErrorCount'
|
|
14
14
|
| 'getRejectionCount'
|
|
15
15
|
| 'getRemainingInWindow'
|
|
16
16
|
| 'getMsUntilNextWindow'
|
|
17
17
|
> {
|
|
18
|
-
|
|
18
|
+
successCount: Accessor<number>
|
|
19
|
+
settleCount: Accessor<number>
|
|
20
|
+
errorCount: Accessor<number>
|
|
19
21
|
rejectionCount: Accessor<number>
|
|
20
22
|
remainingInWindow: Accessor<number>
|
|
21
23
|
msUntilNextWindow: Accessor<number>
|
|
@@ -57,21 +59,24 @@ export interface SolidAsyncRateLimiter<
|
|
|
57
59
|
* );
|
|
58
60
|
* ```
|
|
59
61
|
*/
|
|
60
|
-
export function createAsyncRateLimiter<
|
|
61
|
-
TFn extends AnyAsyncFunction,
|
|
62
|
-
TArgs extends Parameters<TFn>,
|
|
63
|
-
>(
|
|
62
|
+
export function createAsyncRateLimiter<TFn extends AnyAsyncFunction>(
|
|
64
63
|
fn: TFn,
|
|
65
|
-
initialOptions: AsyncRateLimiterOptions<TFn
|
|
66
|
-
): SolidAsyncRateLimiter<TFn
|
|
67
|
-
const asyncRateLimiter = new AsyncRateLimiter<TFn
|
|
64
|
+
initialOptions: AsyncRateLimiterOptions<TFn>,
|
|
65
|
+
): SolidAsyncRateLimiter<TFn> {
|
|
66
|
+
const asyncRateLimiter = new AsyncRateLimiter<TFn>(fn, initialOptions)
|
|
68
67
|
|
|
69
|
-
const [
|
|
70
|
-
asyncRateLimiter.
|
|
68
|
+
const [successCount, setSuccessCount] = createSignal(
|
|
69
|
+
asyncRateLimiter.getSuccessCount(),
|
|
71
70
|
)
|
|
72
71
|
const [rejectionCount, setRejectionCount] = createSignal(
|
|
73
72
|
asyncRateLimiter.getRejectionCount(),
|
|
74
73
|
)
|
|
74
|
+
const [errorCount, setErrorCount] = createSignal(
|
|
75
|
+
asyncRateLimiter.getErrorCount(),
|
|
76
|
+
)
|
|
77
|
+
const [settleCount, setSettleCount] = createSignal(
|
|
78
|
+
asyncRateLimiter.getSettleCount(),
|
|
79
|
+
)
|
|
75
80
|
const [remainingInWindow, setRemainingInWindow] = createSignal(
|
|
76
81
|
asyncRateLimiter.getRemainingInWindow(),
|
|
77
82
|
)
|
|
@@ -79,18 +84,19 @@ export function createAsyncRateLimiter<
|
|
|
79
84
|
asyncRateLimiter.getMsUntilNextWindow(),
|
|
80
85
|
)
|
|
81
86
|
|
|
82
|
-
function setOptions(
|
|
83
|
-
newOptions: Partial<AsyncRateLimiterOptions<TFn, TArgs>>,
|
|
84
|
-
) {
|
|
87
|
+
function setOptions(newOptions: Partial<AsyncRateLimiterOptions<TFn>>) {
|
|
85
88
|
asyncRateLimiter.setOptions({
|
|
86
89
|
...newOptions,
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
onSettled: (rateLimiter) => {
|
|
91
|
+
setSuccessCount(rateLimiter.getSuccessCount())
|
|
92
|
+
setSettleCount(rateLimiter.getSettleCount())
|
|
93
|
+
setErrorCount(rateLimiter.getErrorCount())
|
|
94
|
+
setRejectionCount(rateLimiter.getRejectionCount())
|
|
89
95
|
setRemainingInWindow(rateLimiter.getRemainingInWindow())
|
|
90
96
|
setMsUntilNextWindow(rateLimiter.getMsUntilNextWindow())
|
|
91
97
|
|
|
92
|
-
const
|
|
93
|
-
|
|
98
|
+
const onSettled = newOptions.onSettled ?? initialOptions.onSettled
|
|
99
|
+
onSettled?.(rateLimiter)
|
|
94
100
|
},
|
|
95
101
|
onReject: (rateLimiter) => {
|
|
96
102
|
setRejectionCount(rateLimiter.getRejectionCount())
|
|
@@ -107,10 +113,12 @@ export function createAsyncRateLimiter<
|
|
|
107
113
|
|
|
108
114
|
return {
|
|
109
115
|
...bindInstanceMethods(asyncRateLimiter),
|
|
110
|
-
|
|
111
|
-
rejectionCount,
|
|
116
|
+
errorCount,
|
|
112
117
|
remainingInWindow,
|
|
113
118
|
msUntilNextWindow,
|
|
119
|
+
rejectionCount,
|
|
114
120
|
setOptions,
|
|
115
|
-
|
|
121
|
+
settleCount,
|
|
122
|
+
successCount,
|
|
123
|
+
} as SolidAsyncRateLimiter<TFn>
|
|
116
124
|
}
|
|
@@ -5,18 +5,24 @@ import type { Accessor } from 'solid-js'
|
|
|
5
5
|
import type { AnyAsyncFunction } from '@tanstack/pacer/types'
|
|
6
6
|
import type { AsyncThrottlerOptions } from '@tanstack/pacer/async-throttler'
|
|
7
7
|
|
|
8
|
-
export interface SolidAsyncThrottler<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
| '
|
|
8
|
+
export interface SolidAsyncThrottler<TFn extends AnyAsyncFunction>
|
|
9
|
+
extends Omit<
|
|
10
|
+
AsyncThrottler<TFn>,
|
|
11
|
+
| 'getSuccessCount'
|
|
12
|
+
| 'getSettleCount'
|
|
13
|
+
| 'getErrorCount'
|
|
14
14
|
| 'getIsPending'
|
|
15
|
+
| 'getIsExecuting'
|
|
16
|
+
| 'getLastResult'
|
|
15
17
|
| 'getLastExecutionTime'
|
|
16
18
|
| 'getNextExecutionTime'
|
|
17
19
|
> {
|
|
18
|
-
|
|
20
|
+
successCount: Accessor<number>
|
|
21
|
+
settleCount: Accessor<number>
|
|
22
|
+
errorCount: Accessor<number>
|
|
19
23
|
isPending: Accessor<boolean>
|
|
24
|
+
isExecuting: Accessor<boolean>
|
|
25
|
+
lastResult: Accessor<ReturnType<TFn> | undefined>
|
|
20
26
|
lastExecutionTime: Accessor<number>
|
|
21
27
|
nextExecutionTime: Accessor<number>
|
|
22
28
|
}
|
|
@@ -58,19 +64,30 @@ export interface SolidAsyncThrottler<
|
|
|
58
64
|
* ```
|
|
59
65
|
*/
|
|
60
66
|
|
|
61
|
-
export function createAsyncThrottler<
|
|
62
|
-
TFn extends AnyAsyncFunction,
|
|
63
|
-
TArgs extends Parameters<TFn>,
|
|
64
|
-
>(
|
|
67
|
+
export function createAsyncThrottler<TFn extends AnyAsyncFunction>(
|
|
65
68
|
fn: TFn,
|
|
66
|
-
initialOptions: AsyncThrottlerOptions<TFn
|
|
67
|
-
): SolidAsyncThrottler<TFn
|
|
68
|
-
const asyncThrottler =
|
|
69
|
+
initialOptions: AsyncThrottlerOptions<TFn>,
|
|
70
|
+
): SolidAsyncThrottler<TFn> {
|
|
71
|
+
const asyncThrottler = bindInstanceMethods(
|
|
72
|
+
new AsyncThrottler<TFn>(fn, initialOptions),
|
|
73
|
+
)
|
|
69
74
|
|
|
70
|
-
const [
|
|
71
|
-
asyncThrottler.
|
|
75
|
+
const [successCount, setSuccessCount] = createSignal(
|
|
76
|
+
asyncThrottler.getSuccessCount(),
|
|
77
|
+
)
|
|
78
|
+
const [settleCount, setSettleCount] = createSignal(
|
|
79
|
+
asyncThrottler.getSettleCount(),
|
|
80
|
+
)
|
|
81
|
+
const [errorCount, setErrorCount] = createSignal(
|
|
82
|
+
asyncThrottler.getErrorCount(),
|
|
72
83
|
)
|
|
73
84
|
const [isPending, setIsPending] = createSignal(asyncThrottler.getIsPending())
|
|
85
|
+
const [isExecuting, setIsExecuting] = createSignal(
|
|
86
|
+
asyncThrottler.getIsExecuting(),
|
|
87
|
+
)
|
|
88
|
+
const [lastResult, setLastResult] = createSignal(
|
|
89
|
+
asyncThrottler.getLastResult(),
|
|
90
|
+
)
|
|
74
91
|
const [lastExecutionTime, setLastExecutionTime] = createSignal(
|
|
75
92
|
asyncThrottler.getLastExecutionTime(),
|
|
76
93
|
)
|
|
@@ -78,17 +95,21 @@ export function createAsyncThrottler<
|
|
|
78
95
|
asyncThrottler.getNextExecutionTime(),
|
|
79
96
|
)
|
|
80
97
|
|
|
81
|
-
function setOptions(newOptions: Partial<AsyncThrottlerOptions<TFn
|
|
98
|
+
function setOptions(newOptions: Partial<AsyncThrottlerOptions<TFn>>) {
|
|
82
99
|
asyncThrottler.setOptions({
|
|
83
100
|
...newOptions,
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
onSettled: (throttler) => {
|
|
102
|
+
setSuccessCount(throttler.getSuccessCount())
|
|
103
|
+
setSettleCount(throttler.getSettleCount())
|
|
104
|
+
setErrorCount(throttler.getErrorCount())
|
|
86
105
|
setIsPending(throttler.getIsPending())
|
|
106
|
+
setIsExecuting(throttler.getIsExecuting())
|
|
87
107
|
setLastExecutionTime(throttler.getLastExecutionTime())
|
|
88
108
|
setNextExecutionTime(throttler.getNextExecutionTime())
|
|
109
|
+
setLastResult(throttler.getLastResult())
|
|
89
110
|
|
|
90
|
-
const
|
|
91
|
-
|
|
111
|
+
const onSettled = newOptions.onSettled ?? initialOptions.onSettled
|
|
112
|
+
onSettled?.(throttler)
|
|
92
113
|
},
|
|
93
114
|
})
|
|
94
115
|
}
|
|
@@ -96,11 +117,15 @@ export function createAsyncThrottler<
|
|
|
96
117
|
setOptions(initialOptions)
|
|
97
118
|
|
|
98
119
|
return {
|
|
99
|
-
...
|
|
100
|
-
|
|
120
|
+
...asyncThrottler,
|
|
121
|
+
errorCount,
|
|
122
|
+
isExecuting,
|
|
101
123
|
isPending,
|
|
102
124
|
lastExecutionTime,
|
|
125
|
+
lastResult,
|
|
103
126
|
nextExecutionTime,
|
|
104
127
|
setOptions,
|
|
105
|
-
|
|
128
|
+
settleCount,
|
|
129
|
+
successCount,
|
|
130
|
+
} as SolidAsyncThrottler<TFn>
|
|
106
131
|
}
|
|
@@ -45,12 +45,8 @@ import type { DebouncerOptions } from '@tanstack/pacer/debouncer'
|
|
|
45
45
|
*/
|
|
46
46
|
export function createDebouncedSignal<TValue>(
|
|
47
47
|
value: TValue,
|
|
48
|
-
initialOptions: DebouncerOptions<Setter<TValue
|
|
49
|
-
): [
|
|
50
|
-
Accessor<TValue>,
|
|
51
|
-
Setter<TValue>,
|
|
52
|
-
SolidDebouncer<Setter<TValue>, [Accessor<TValue>]>,
|
|
53
|
-
] {
|
|
48
|
+
initialOptions: DebouncerOptions<Setter<TValue>>,
|
|
49
|
+
): [Accessor<TValue>, Setter<TValue>, SolidDebouncer<Setter<TValue>>] {
|
|
54
50
|
const [debouncedValue, setDebouncedValue] = createSignal<TValue>(value)
|
|
55
51
|
|
|
56
52
|
const debouncer = createDebouncer(setDebouncedValue, initialOptions)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEffect
|
|
1
|
+
import { createEffect } from 'solid-js'
|
|
2
2
|
import { createDebouncedSignal } from './createDebouncedSignal'
|
|
3
3
|
import type { SolidDebouncer } from './createDebouncer'
|
|
4
4
|
import type { Accessor, Setter } from 'solid-js'
|
|
@@ -18,8 +18,8 @@ import type { DebouncerOptions } from '@tanstack/pacer/debouncer'
|
|
|
18
18
|
* or calculations occur.
|
|
19
19
|
*
|
|
20
20
|
* The hook returns a tuple containing:
|
|
21
|
-
* -
|
|
22
|
-
* - The debouncer instance with control methods
|
|
21
|
+
* - An Accessor that provides the current debounced value
|
|
22
|
+
* - The debouncer instance with control methods
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```tsx
|
|
@@ -34,20 +34,14 @@ import type { DebouncerOptions } from '@tanstack/pacer/debouncer'
|
|
|
34
34
|
* fetchSearchResults(debouncedQuery());
|
|
35
35
|
* });
|
|
36
36
|
*
|
|
37
|
-
* //
|
|
38
|
-
*
|
|
39
|
-
* console.log('Is pending:', debouncer.isPending());
|
|
40
|
-
*
|
|
41
|
-
* // Handle input changes
|
|
42
|
-
* const handleChange = (e) => {
|
|
43
|
-
* setSearchQuery(e.target.value);
|
|
44
|
-
* };
|
|
37
|
+
* // Control the debouncer
|
|
38
|
+
* debouncer.cancel(); // Cancel any pending updates
|
|
45
39
|
* ```
|
|
46
40
|
*/
|
|
47
41
|
export function createDebouncedValue<TValue>(
|
|
48
42
|
value: Accessor<TValue>,
|
|
49
|
-
initialOptions: DebouncerOptions<Setter<TValue
|
|
50
|
-
): [Accessor<TValue>, SolidDebouncer<Setter<TValue
|
|
43
|
+
initialOptions: DebouncerOptions<Setter<TValue>>,
|
|
44
|
+
): [Accessor<TValue>, SolidDebouncer<Setter<TValue>>] {
|
|
51
45
|
const [debouncedValue, setDebouncedValue, debouncer] = createDebouncedSignal(
|
|
52
46
|
value(),
|
|
53
47
|
initialOptions,
|
|
@@ -55,9 +49,6 @@ export function createDebouncedValue<TValue>(
|
|
|
55
49
|
|
|
56
50
|
createEffect(() => {
|
|
57
51
|
setDebouncedValue(value() as any)
|
|
58
|
-
onCleanup(() => {
|
|
59
|
-
debouncer.cancel()
|
|
60
|
-
})
|
|
61
52
|
})
|
|
62
53
|
|
|
63
54
|
return [debouncedValue, debouncer]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Debouncer } from '@tanstack/pacer/debouncer'
|
|
2
|
-
import { createSignal } from 'solid-js'
|
|
2
|
+
import { createEffect, createSignal, onCleanup } from 'solid-js'
|
|
3
3
|
import { bindInstanceMethods } from '@tanstack/pacer/utils'
|
|
4
4
|
import type { Accessor } from 'solid-js'
|
|
5
5
|
import type { AnyFunction } from '@tanstack/pacer/types'
|
|
@@ -8,10 +8,8 @@ import type { DebouncerOptions } from '@tanstack/pacer/debouncer'
|
|
|
8
8
|
/**
|
|
9
9
|
* An extension of the Debouncer class that adds Solid signals to access the internal state of the debouncer
|
|
10
10
|
*/
|
|
11
|
-
export interface SolidDebouncer<
|
|
12
|
-
TFn
|
|
13
|
-
TArgs extends Parameters<TFn>,
|
|
14
|
-
> extends Omit<Debouncer<TFn, TArgs>, 'getExecutionCount' | 'getIsPending'> {
|
|
11
|
+
export interface SolidDebouncer<TFn extends AnyFunction>
|
|
12
|
+
extends Omit<Debouncer<TFn>, 'getExecutionCount' | 'getIsPending'> {
|
|
15
13
|
executionCount: Accessor<number>
|
|
16
14
|
isPending: Accessor<boolean>
|
|
17
15
|
}
|
|
@@ -52,21 +50,18 @@ export interface SolidDebouncer<
|
|
|
52
50
|
* debouncer.setOptions({ wait: 1000 });
|
|
53
51
|
* ```
|
|
54
52
|
*/
|
|
55
|
-
export function createDebouncer<
|
|
56
|
-
TFn extends AnyFunction,
|
|
57
|
-
TArgs extends Parameters<TFn>,
|
|
58
|
-
>(
|
|
53
|
+
export function createDebouncer<TFn extends AnyFunction>(
|
|
59
54
|
fn: TFn,
|
|
60
|
-
initialOptions: DebouncerOptions<TFn
|
|
61
|
-
): SolidDebouncer<TFn
|
|
62
|
-
const debouncer = new Debouncer<TFn
|
|
55
|
+
initialOptions: DebouncerOptions<TFn>,
|
|
56
|
+
): SolidDebouncer<TFn> {
|
|
57
|
+
const debouncer = bindInstanceMethods(new Debouncer<TFn>(fn, initialOptions))
|
|
63
58
|
|
|
64
59
|
const [executionCount, setExecutionCount] = createSignal(
|
|
65
60
|
debouncer.getExecutionCount(),
|
|
66
61
|
)
|
|
67
62
|
const [isPending, setIsPending] = createSignal(debouncer.getIsPending())
|
|
68
63
|
|
|
69
|
-
function setOptions(newOptions: Partial<DebouncerOptions<TFn
|
|
64
|
+
function setOptions(newOptions: Partial<DebouncerOptions<TFn>>) {
|
|
70
65
|
debouncer.setOptions({
|
|
71
66
|
...newOptions,
|
|
72
67
|
onExecute: (debouncer) => {
|
|
@@ -81,10 +76,16 @@ export function createDebouncer<
|
|
|
81
76
|
|
|
82
77
|
setOptions(initialOptions)
|
|
83
78
|
|
|
79
|
+
createEffect(() => {
|
|
80
|
+
onCleanup(() => {
|
|
81
|
+
debouncer.cancel()
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
84
85
|
return {
|
|
85
|
-
...
|
|
86
|
+
...debouncer,
|
|
86
87
|
executionCount,
|
|
87
88
|
isPending,
|
|
88
89
|
setOptions,
|
|
89
|
-
}
|
|
90
|
+
} as SolidDebouncer<TFn>
|
|
90
91
|
}
|
|
@@ -44,6 +44,10 @@ export interface SolidQueuer<TValue>
|
|
|
44
44
|
* Signal version of `getPeek`
|
|
45
45
|
*/
|
|
46
46
|
peek: Accessor<TValue | undefined>
|
|
47
|
+
/**
|
|
48
|
+
* Signal version of `getRejectionCount`
|
|
49
|
+
*/
|
|
50
|
+
rejectionCount: Accessor<number>
|
|
47
51
|
/**
|
|
48
52
|
* Signal version of `getSize`
|
|
49
53
|
*/
|
|
@@ -98,7 +102,7 @@ export interface SolidQueuer<TValue>
|
|
|
98
102
|
export function createQueuer<TValue>(
|
|
99
103
|
initialOptions: QueuerOptions<TValue> = {},
|
|
100
104
|
): SolidQueuer<TValue> {
|
|
101
|
-
const queuer = new Queuer<TValue>(initialOptions)
|
|
105
|
+
const queuer = bindInstanceMethods(new Queuer<TValue>(initialOptions))
|
|
102
106
|
|
|
103
107
|
const [allItems, setAllItems] = createSignal<Array<TValue>>(
|
|
104
108
|
queuer.getAllItems(),
|
|
@@ -152,7 +156,7 @@ export function createQueuer<TValue>(
|
|
|
152
156
|
setOptions(initialOptions)
|
|
153
157
|
|
|
154
158
|
return {
|
|
155
|
-
...
|
|
159
|
+
...queuer,
|
|
156
160
|
allItems,
|
|
157
161
|
executionCount,
|
|
158
162
|
isEmpty,
|
|
@@ -163,5 +167,5 @@ export function createQueuer<TValue>(
|
|
|
163
167
|
rejectionCount,
|
|
164
168
|
size,
|
|
165
169
|
setOptions,
|
|
166
|
-
}
|
|
170
|
+
} as SolidQueuer<TValue>
|
|
167
171
|
}
|
|
@@ -56,12 +56,8 @@ import type { RateLimiterOptions } from '@tanstack/pacer/rate-limiter'
|
|
|
56
56
|
*/
|
|
57
57
|
export function createRateLimitedSignal<TValue>(
|
|
58
58
|
value: TValue,
|
|
59
|
-
initialOptions: RateLimiterOptions<Setter<TValue
|
|
60
|
-
): [
|
|
61
|
-
Accessor<TValue>,
|
|
62
|
-
Setter<TValue>,
|
|
63
|
-
SolidRateLimiter<Setter<TValue>, [Accessor<TValue>]>,
|
|
64
|
-
] {
|
|
59
|
+
initialOptions: RateLimiterOptions<Setter<TValue>>,
|
|
60
|
+
): [Accessor<TValue>, Setter<TValue>, SolidRateLimiter<Setter<TValue>>] {
|
|
65
61
|
const [rateLimitedValue, setRateLimitedValue] = createSignal<TValue>(value)
|
|
66
62
|
|
|
67
63
|
const rateLimiter = createRateLimiter(setRateLimitedValue, initialOptions)
|