time-queues 1.2.4 → 1.3.1
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/README.md +117 -36
- package/llms-full.txt +430 -0
- package/llms.txt +95 -0
- package/package.json +43 -12
- package/src/CancelTaskError.d.ts +2 -1
- package/src/CancelTaskError.js +2 -4
- package/src/Counter.d.ts +0 -1
- package/src/Counter.js +0 -2
- package/src/FrameQueue.d.ts +2 -2
- package/src/FrameQueue.js +0 -2
- package/src/IdleQueue.d.ts +2 -2
- package/src/IdleQueue.js +0 -2
- package/src/LimitedQueue.d.ts +104 -0
- package/src/LimitedQueue.js +78 -0
- package/src/ListQueue.d.ts +1 -6
- package/src/ListQueue.js +18 -3
- package/src/MicroTask.d.ts +7 -1
- package/src/MicroTask.js +47 -15
- package/src/MicroTaskQueue.d.ts +24 -20
- package/src/MicroTaskQueue.js +22 -7
- package/src/PageWatcher.d.ts +2 -2
- package/src/PageWatcher.js +0 -2
- package/src/Retainer.d.ts +4 -4
- package/src/Retainer.js +0 -2
- package/src/Scheduler.d.ts +23 -17
- package/src/Scheduler.js +1 -2
- package/src/Throttler.d.ts +7 -2
- package/src/Throttler.js +1 -2
- package/src/audit.js +0 -2
- package/src/batch.d.ts +16 -0
- package/src/batch.js +40 -0
- package/src/debounce.js +0 -2
- package/src/defer.d.ts +3 -4
- package/src/defer.js +0 -2
- package/src/index.d.ts +7 -2
- package/src/random-dist.d.ts +31 -0
- package/src/random-dist.js +27 -0
- package/src/random-sleep.d.ts +57 -0
- package/src/random-sleep.js +27 -0
- package/src/sample.d.ts +1 -1
- package/src/sample.js +0 -2
- package/src/sleep.d.ts +1 -1
- package/src/sleep.js +0 -2
- package/src/throttle.d.ts +2 -1
- package/src/throttle.js +0 -2
- package/src/when-dom-loaded.d.ts +4 -8
- package/src/when-dom-loaded.js +3 -9
- package/src/when-loaded.d.ts +4 -8
- package/src/when-loaded.js +3 -9
package/README.md
CHANGED
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
[npm-img]: https://img.shields.io/npm/v/time-queues.svg
|
|
4
4
|
[npm-url]: https://npmjs.org/package/time-queues
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Lightweight library for asynchronous task scheduling and concurrency control in JavaScript. Works in browsers, Node.js, Deno, and Bun.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Why time-queues?
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Modern web apps need to schedule work without blocking the main thread, respect page lifecycle events, and limit concurrency — but the platform APIs are low-level and tedious to use correctly. `time-queues` wraps them in a small, composable toolkit:
|
|
11
11
|
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
12
|
+
- **Schedule tasks** to run after a delay, at a specific time, or on a recurring interval
|
|
13
|
+
- **Optimize browser performance** by running work during idle periods or animation frames
|
|
14
|
+
- **React to page lifecycle** changes (hidden, frozen, terminated) automatically
|
|
15
|
+
- **Control concurrency** with throttling, debouncing, batching, and rate limiting
|
|
16
|
+
- **Manage resources** with reference-counted creation/destruction
|
|
17
|
+
- **Minimal footprint** — one dependency ([list-toolkit](https://www.npmjs.com/package/list-toolkit), zero-dep)
|
|
17
18
|
|
|
18
19
|
## Installation
|
|
19
20
|
|
|
@@ -21,57 +22,137 @@ The library provides elegant solutions for common timing and scheduling challeng
|
|
|
21
22
|
npm install time-queues
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import sleep from 'time-queues/sleep.js';
|
|
29
|
+
import {Scheduler, repeat} from 'time-queues/Scheduler.js';
|
|
30
|
+
import {batch} from 'time-queues/batch.js';
|
|
31
|
+
|
|
32
|
+
// Simple delay
|
|
33
|
+
await sleep(1000);
|
|
34
|
+
|
|
35
|
+
// Run a task every 5 seconds
|
|
36
|
+
const scheduler = new Scheduler();
|
|
37
|
+
scheduler.enqueue(
|
|
38
|
+
repeat(({task, scheduler}) => {
|
|
39
|
+
console.log('tick');
|
|
40
|
+
}, 5000),
|
|
41
|
+
5000
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Fetch 10 URLs, max 3 at a time
|
|
45
|
+
const results = await batch(
|
|
46
|
+
urls.map(url => () => fetch(url).then(r => r.json())),
|
|
47
|
+
3
|
|
48
|
+
);
|
|
30
49
|
```
|
|
31
50
|
|
|
32
|
-
|
|
51
|
+
See the [wiki](https://github.com/uhop/time-queues/wiki) for more use cases.
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
The [project wiki](https://github.com/uhop/time-queues/wiki) has detailed docs for every component.
|
|
56
|
+
|
|
57
|
+
### Queues
|
|
58
|
+
|
|
59
|
+
| Component | Purpose |
|
|
60
|
+
| --------------------------------------------------------------------- | --------------------------------------------------- |
|
|
61
|
+
| [Scheduler](https://github.com/uhop/time-queues/wiki/Scheduler) | Time-based task scheduling (delays, dates, repeats) |
|
|
62
|
+
| [IdleQueue](https://github.com/uhop/time-queues/wiki/IdleQueue) | Run tasks during browser idle periods |
|
|
63
|
+
| [FrameQueue](https://github.com/uhop/time-queues/wiki/FrameQueue) | Run tasks in animation frames |
|
|
64
|
+
| [LimitedQueue](https://github.com/uhop/time-queues/wiki/LimitedQueue) | Concurrency-controlled async queue |
|
|
65
|
+
| [PageWatcher](https://github.com/uhop/time-queues/wiki/PageWatcher) | React to page lifecycle changes |
|
|
66
|
+
|
|
67
|
+
### Utilities
|
|
68
|
+
|
|
69
|
+
| Function | Purpose |
|
|
70
|
+
| ------------------------------------------------------------------- | --------------------------------------- |
|
|
71
|
+
| [sleep()](<https://github.com/uhop/time-queues/wiki/sleep()>) | Promise-based delay |
|
|
72
|
+
| [defer()](<https://github.com/uhop/time-queues/wiki/defer()>) | Execute on next tick |
|
|
73
|
+
| [throttle()](<https://github.com/uhop/time-queues/wiki/throttle()>) | Rate-limit a function (first call wins) |
|
|
74
|
+
| [debounce()](<https://github.com/uhop/time-queues/wiki/debounce()>) | Delay until input stabilizes |
|
|
75
|
+
| [sample()](<https://github.com/uhop/time-queues/wiki/sample()>) | Sample at regular intervals |
|
|
76
|
+
| [audit()](<https://github.com/uhop/time-queues/wiki/audit()>) | Collect then execute after delay |
|
|
77
|
+
| [batch()](<https://github.com/uhop/time-queues/wiki/batch()>) | Run async ops with concurrency limit |
|
|
78
|
+
|
|
79
|
+
### Supporting Classes
|
|
80
|
+
|
|
81
|
+
| Component | Purpose |
|
|
82
|
+
| ------------------------------------------------------------------------- | ------------------------------- |
|
|
83
|
+
| [Throttler](https://github.com/uhop/time-queues/wiki/Throttler) | Key-based rate limiting |
|
|
84
|
+
| [Retainer](https://github.com/uhop/time-queues/wiki/Retainer) | Resource lifecycle management |
|
|
85
|
+
| [Counter](https://github.com/uhop/time-queues/wiki/Counter) | Track pending task counts |
|
|
86
|
+
| [MicroTask](https://github.com/uhop/time-queues/wiki/MicroTask) | Base task unit |
|
|
87
|
+
| [MicroTaskQueue](https://github.com/uhop/time-queues/wiki/MicroTaskQueue) | Base queue class |
|
|
88
|
+
| [ListQueue](https://github.com/uhop/time-queues/wiki/ListQueue) | List-based queue implementation |
|
|
33
89
|
|
|
34
|
-
|
|
90
|
+
### Random Utilities
|
|
35
91
|
|
|
36
|
-
|
|
92
|
+
| Module | Purpose |
|
|
93
|
+
| --------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
94
|
+
| [random-dist](https://github.com/uhop/time-queues/wiki/random-dist) | Random numbers (uniform, normal, exponential, Pareto) |
|
|
95
|
+
| [random-sleep](https://github.com/uhop/time-queues/wiki/random-sleep) | Randomized delays from various distributions |
|
|
37
96
|
|
|
38
|
-
|
|
39
|
-
- [Retainer](https://github.com/uhop/time-queues/wiki/Retainer): Manage resource lifecycle
|
|
40
|
-
- [Throttler](https://github.com/uhop/time-queues/wiki/Throttler): Control execution rate based on keys
|
|
41
|
-
- [Counter](https://github.com/uhop/time-queues/wiki/Counter): Track the number of pending tasks asynchronously
|
|
97
|
+
### Page Load Helpers
|
|
42
98
|
|
|
43
|
-
|
|
99
|
+
| Function | Purpose |
|
|
100
|
+
| ----------------------------------------------------------------------------- | ---------------------------------- |
|
|
101
|
+
| [whenDomLoaded()](<https://github.com/uhop/time-queues/wiki/whenDomLoaded()>) | Run code when DOM is ready |
|
|
102
|
+
| [whenLoaded()](<https://github.com/uhop/time-queues/wiki/whenLoaded()>) | Run code when page is fully loaded |
|
|
44
103
|
|
|
45
|
-
|
|
46
|
-
- [FrameQueue](https://github.com/uhop/time-queues/wiki/FrameQueue): Execute tasks during animation frames
|
|
47
|
-
- [PageWatcher](https://github.com/uhop/time-queues/wiki/PageWatcher): Monitor and respond to page lifecycle changes
|
|
104
|
+
## Browser Notes
|
|
48
105
|
|
|
49
|
-
|
|
106
|
+
The library leverages these browser APIs where available:
|
|
50
107
|
|
|
51
|
-
- [
|
|
52
|
-
- [
|
|
53
|
-
- [
|
|
54
|
-
- [
|
|
55
|
-
|
|
56
|
-
|
|
108
|
+
- [requestIdleCallback()](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)
|
|
109
|
+
- [requestAnimationFrame()](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
|
|
110
|
+
- [queueMicrotask()](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
|
111
|
+
- [Page Lifecycle API](https://developer.chrome.com/docs/web-platform/page-lifecycle-api)
|
|
112
|
+
|
|
113
|
+
For background reading:
|
|
114
|
+
|
|
115
|
+
- [Background Tasks API](https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API)
|
|
116
|
+
- [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API)
|
|
117
|
+
|
|
118
|
+
### Test web app
|
|
119
|
+
|
|
120
|
+
Run `npm start` and open [http://localhost:3000/tests/web/](http://localhost:3000/tests/web/) —
|
|
121
|
+
open the console, switch tabs, navigate away and back to see queues in action.
|
|
122
|
+
Source: [tests/web/test.js](https://github.com/uhop/time-queues/blob/main/tests/web/test.js).
|
|
123
|
+
|
|
124
|
+
## AI Integration
|
|
125
|
+
|
|
126
|
+
This project ships [llms.txt](llms.txt) and [llms-full.txt](llms-full.txt) for AI agents and LLMs. Contributors and AI coding assistants should see [AGENTS.md](AGENTS.md) for project conventions.
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
git clone --recurse-submodules https://github.com/uhop/time-queues.git
|
|
132
|
+
cd time-queues
|
|
133
|
+
npm install
|
|
134
|
+
npm test
|
|
135
|
+
```
|
|
57
136
|
|
|
58
137
|
## License
|
|
59
138
|
|
|
60
|
-
|
|
139
|
+
BSD-3-Clause
|
|
61
140
|
|
|
62
141
|
## Release History
|
|
63
142
|
|
|
143
|
+
- 1.3.1 _Fixed `.d.ts` declarations, consolidated TS typing tests, improved documentation._
|
|
144
|
+
- 1.3.0 _Added `batch()`, `LimitedQueue`, random distributions and random sleep functions._
|
|
64
145
|
- 1.2.4 _Updated dependencies._
|
|
65
146
|
- 1.2.3 _Updated dependencies._
|
|
66
147
|
- 1.2.2 _`Counter`: separated old waiter from new waiters before notifying them._
|
|
67
148
|
- 1.2.1 _Minor release: updated formal TS dependencies in `index.d.ts`._
|
|
68
|
-
- 1.2.0 _Added `Counter`.
|
|
69
|
-
- 1.1.2 _Updated dev dependencies.
|
|
149
|
+
- 1.2.0 _Added `Counter`._
|
|
150
|
+
- 1.1.2 _Updated dev dependencies._
|
|
70
151
|
- 1.1.1 _Updates to TS typings._
|
|
71
152
|
- 1.1.0 _Added `Throttler`, `Retainer`, promise-based convenience time methods._
|
|
72
153
|
- 1.0.5 _Technical release: updated deps, more tests._
|
|
73
154
|
- 1.0.4 _Bug fixes and code simplifications._
|
|
74
155
|
- 1.0.3 _Updated deps (`list-toolkit`) to fix a minor bug._
|
|
75
156
|
- 1.0.2 _Updated deps (`list-toolkit`)._
|
|
76
|
-
- 1.0.1 _Minor update in README.
|
|
157
|
+
- 1.0.1 _Minor update in README._
|
|
77
158
|
- 1.0.0 _Initial release._
|
package/llms-full.txt
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# time-queues
|
|
2
|
+
|
|
3
|
+
> Lightweight async task scheduling and concurrency control for JavaScript: schedulers, idle/frame/limited queues, throttle, debounce, batch, page lifecycle, random delays.
|
|
4
|
+
|
|
5
|
+
- NPM: https://npmjs.org/package/time-queues
|
|
6
|
+
- GitHub: https://github.com/uhop/time-queues
|
|
7
|
+
- Wiki: https://github.com/uhop/time-queues/wiki
|
|
8
|
+
- License: BSD-3-Clause
|
|
9
|
+
- Runtime: browsers, Node.js, Bun, Deno
|
|
10
|
+
- Module system: ESM (`"type": "module"`)
|
|
11
|
+
- TypeScript: built-in `.d.ts` declarations for all modules
|
|
12
|
+
- Dependency: [list-toolkit](https://npmjs.org/package/list-toolkit) (zero-dep)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install time-queues
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import sleep from 'time-queues/sleep.js';
|
|
24
|
+
import {Scheduler, repeat} from 'time-queues/Scheduler.js';
|
|
25
|
+
import {batch} from 'time-queues/batch.js';
|
|
26
|
+
|
|
27
|
+
await sleep(1000);
|
|
28
|
+
|
|
29
|
+
const scheduler = new Scheduler();
|
|
30
|
+
scheduler.enqueue(repeat(({task, scheduler}) => {
|
|
31
|
+
console.log('tick');
|
|
32
|
+
}, 5000), 5000);
|
|
33
|
+
|
|
34
|
+
const results = await batch(
|
|
35
|
+
urls.map(url => () => fetch(url).then(r => r.json())),
|
|
36
|
+
3
|
|
37
|
+
);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
MicroTask (single task with promise support)
|
|
44
|
+
└─ Task (Scheduler-specific, adds delay/time)
|
|
45
|
+
|
|
46
|
+
MicroTaskQueue (abstract queue base)
|
|
47
|
+
├─ Scheduler (time-based, uses min-heap)
|
|
48
|
+
└─ ListQueue (linked-list storage)
|
|
49
|
+
├─ IdleQueue (requestIdleCallback)
|
|
50
|
+
├─ FrameQueue (requestAnimationFrame)
|
|
51
|
+
├─ LimitedQueue (concurrency control)
|
|
52
|
+
└─ PageWatcher (page lifecycle events)
|
|
53
|
+
|
|
54
|
+
Standalone: Counter, Throttler, Retainer, CancelTaskError
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
All modules are ESM. Import as `import X from 'time-queues/<module>.js'`.
|
|
58
|
+
|
|
59
|
+
## API Reference
|
|
60
|
+
|
|
61
|
+
### CancelTaskError (`time-queues/CancelTaskError.js`)
|
|
62
|
+
|
|
63
|
+
Error subclass for task cancellation signals.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
class CancelTaskError extends Error {
|
|
67
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
68
|
+
}
|
|
69
|
+
export default CancelTaskError;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### MicroTask (`time-queues/MicroTask.js`)
|
|
73
|
+
|
|
74
|
+
Base task unit with lazy promise creation.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
class MicroTask {
|
|
78
|
+
fn: () => unknown;
|
|
79
|
+
isCanceled: boolean;
|
|
80
|
+
get promise(): Promise<unknown> | null;
|
|
81
|
+
constructor(fn: () => unknown);
|
|
82
|
+
makePromise(): this;
|
|
83
|
+
resolve(value: unknown): this;
|
|
84
|
+
cancel(error?: Error): this;
|
|
85
|
+
}
|
|
86
|
+
export default MicroTask;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### MicroTaskQueue (`time-queues/MicroTaskQueue.js`)
|
|
90
|
+
|
|
91
|
+
Abstract queue base class.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
class MicroTaskQueue {
|
|
95
|
+
paused: boolean;
|
|
96
|
+
constructor(paused?: boolean);
|
|
97
|
+
get isEmpty(): boolean;
|
|
98
|
+
enqueue(fn: () => unknown): MicroTask;
|
|
99
|
+
dequeue(task: MicroTask): this;
|
|
100
|
+
schedule(fn: (() => unknown) | null | undefined, ...args: unknown[]): MicroTask;
|
|
101
|
+
clear(): this;
|
|
102
|
+
pause(): this;
|
|
103
|
+
resume(): this;
|
|
104
|
+
}
|
|
105
|
+
export default MicroTaskQueue;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### ListQueue (`time-queues/ListQueue.js`)
|
|
109
|
+
|
|
110
|
+
Linked-list queue implementation. Extends `MicroTaskQueue`.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
class ListQueue extends MicroTaskQueue {
|
|
114
|
+
paused: boolean;
|
|
115
|
+
stopQueue: (() => void) | null;
|
|
116
|
+
constructor(paused?: boolean);
|
|
117
|
+
get isEmpty(): boolean;
|
|
118
|
+
enqueue(fn: () => unknown): MicroTask;
|
|
119
|
+
dequeue(task: MicroTask): this;
|
|
120
|
+
schedule(fn: (() => unknown) | null | undefined): MicroTask;
|
|
121
|
+
clear(): this;
|
|
122
|
+
pause(): this;
|
|
123
|
+
resume(): this;
|
|
124
|
+
startQueue(): (() => void) | null; // override in subclasses
|
|
125
|
+
}
|
|
126
|
+
export type Task = MicroTask;
|
|
127
|
+
export default ListQueue;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Scheduler (`time-queues/Scheduler.js`)
|
|
131
|
+
|
|
132
|
+
Time-based task scheduling with min-heap. Extends `MicroTaskQueue`.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
class Task extends MicroTask {
|
|
136
|
+
time: number;
|
|
137
|
+
delay: number;
|
|
138
|
+
constructor(delay: number | Date, fn: ({task: Task, scheduler: Scheduler}) => unknown);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
class Scheduler extends MicroTaskQueue {
|
|
142
|
+
paused: boolean;
|
|
143
|
+
tolerance: number;
|
|
144
|
+
constructor(paused?: boolean, tolerance?: number);
|
|
145
|
+
get isEmpty(): boolean;
|
|
146
|
+
get nextTime(): number;
|
|
147
|
+
enqueue(fn: ({task: Task, scheduler: Scheduler}) => unknown, delay: number | Date): Task;
|
|
148
|
+
dequeue(task: Task): this;
|
|
149
|
+
schedule(fn: (({task: Task, scheduler: Scheduler}) => unknown) | null | undefined, delay: number | Date): Task;
|
|
150
|
+
clear(): this;
|
|
151
|
+
pause(): this;
|
|
152
|
+
resume(): this;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const repeat: (fn: ({task: Task, scheduler: Scheduler}) => void, delay: number | Date) => ({task: Task, scheduler: Scheduler}) => void;
|
|
156
|
+
const scheduler: Scheduler; // global instance
|
|
157
|
+
export default scheduler;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Callback receives `{task, scheduler}` as a destructured object.
|
|
161
|
+
|
|
162
|
+
### IdleQueue (`time-queues/IdleQueue.js`)
|
|
163
|
+
|
|
164
|
+
Run tasks during browser idle periods via `requestIdleCallback()`. Extends `ListQueue`.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
class IdleQueue extends ListQueue {
|
|
168
|
+
timeoutBatch: number | undefined;
|
|
169
|
+
options: IdleCallbackOptions | undefined;
|
|
170
|
+
constructor(paused?: boolean, timeoutBatchInMs?: number, options?: IdleCallbackOptions);
|
|
171
|
+
enqueue(fn: ({deadline: IdleDeadline, task: Task, queue: IdleQueue}) => unknown): Task;
|
|
172
|
+
schedule(fn: (({deadline: IdleDeadline, task: Task, queue: IdleQueue}) => unknown) | null | undefined): Task;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const idleQueue: IdleQueue; // global instance
|
|
176
|
+
const defer: (fn: ({deadline: IdleDeadline, task: Task, queue: IdleQueue}) => unknown) => Task;
|
|
177
|
+
export default IdleQueue;
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### FrameQueue (`time-queues/FrameQueue.js`)
|
|
181
|
+
|
|
182
|
+
Run tasks in animation frames via `requestAnimationFrame()`. Extends `ListQueue`.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
class FrameQueue extends ListQueue {
|
|
186
|
+
batch: number | undefined;
|
|
187
|
+
constructor(paused?: boolean, batchInMs?: number);
|
|
188
|
+
enqueue(fn: ({timeStamp: number, task: Task, queue: FrameQueue}) => unknown): Task;
|
|
189
|
+
schedule(fn: (({timeStamp: number, task: Task, queue: FrameQueue}) => unknown) | null | undefined): Task;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const frameQueue: FrameQueue; // global instance
|
|
193
|
+
export default FrameQueue;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### LimitedQueue (`time-queues/LimitedQueue.js`)
|
|
197
|
+
|
|
198
|
+
Concurrency-controlled async queue. Extends `ListQueue`.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
class LimitedQueue extends ListQueue {
|
|
202
|
+
constructor(limit: number, paused?: boolean);
|
|
203
|
+
get taskLimit(): number;
|
|
204
|
+
set taskLimit(limit: number);
|
|
205
|
+
get activeTasks(): number;
|
|
206
|
+
get isIdle(): boolean;
|
|
207
|
+
waitForIdle(): Promise<void>;
|
|
208
|
+
enqueue(fn: () => unknown): Task;
|
|
209
|
+
schedule(fn: (() => unknown) | null | undefined): Task;
|
|
210
|
+
}
|
|
211
|
+
export { Task };
|
|
212
|
+
export default LimitedQueue;
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### PageWatcher (`time-queues/PageWatcher.js`)
|
|
216
|
+
|
|
217
|
+
React to page lifecycle changes. Extends `ListQueue`.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
type PageState = 'active' | 'passive' | 'hidden' | 'frozen' | 'terminated';
|
|
221
|
+
|
|
222
|
+
class PageWatcher extends ListQueue {
|
|
223
|
+
currentState: PageState;
|
|
224
|
+
constructor(started?: boolean);
|
|
225
|
+
enqueue(fn: (state: PageState, previousState: PageState, task: Task, queue: ListQueue) => void, initialize?: boolean): Task;
|
|
226
|
+
schedule(): never; // always throws
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const watchStates: (queue: ListQueue, resumeStatesList?: PageState[]) => (state: PageState) => void;
|
|
230
|
+
const pageWatcher: PageWatcher; // global instance
|
|
231
|
+
export default PageWatcher;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Counter (`time-queues/Counter.js`)
|
|
235
|
+
|
|
236
|
+
Numeric counter with async waiting.
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
class Counter {
|
|
240
|
+
count: number;
|
|
241
|
+
constructor(initial?: number);
|
|
242
|
+
get value(): number;
|
|
243
|
+
set value(value: number);
|
|
244
|
+
increment(): void;
|
|
245
|
+
decrement(): void;
|
|
246
|
+
advance(amount?: number): void;
|
|
247
|
+
waitForZero(): Promise<number>;
|
|
248
|
+
waitFor(fn: (count: number) => boolean): Promise<number>;
|
|
249
|
+
clearWaiters(): void;
|
|
250
|
+
}
|
|
251
|
+
export default Counter;
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Throttler (`time-queues/Throttler.js`)
|
|
255
|
+
|
|
256
|
+
Key-based rate limiting with vacuum cleanup.
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
type ThrottlerOptions = {
|
|
260
|
+
throttleTimeout?: number; // default: 1000
|
|
261
|
+
neverSeenTimeout?: number; // default: 0
|
|
262
|
+
vacuumPeriod?: number; // default: throttleTimeout * 3
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
class Throttler implements ThrottlerOptions {
|
|
266
|
+
throttleTimeout: number;
|
|
267
|
+
neverSeenTimeout: number;
|
|
268
|
+
vacuumPeriod: number;
|
|
269
|
+
lastSeen: Map<unknown, number>;
|
|
270
|
+
constructor(options?: ThrottlerOptions);
|
|
271
|
+
getLastSeen(key: unknown): number;
|
|
272
|
+
getDelay(key: unknown): number;
|
|
273
|
+
wait(key: unknown): Promise<void>;
|
|
274
|
+
get isVacuuming(): boolean;
|
|
275
|
+
startVacuum(): this;
|
|
276
|
+
stopVacuum(): this;
|
|
277
|
+
}
|
|
278
|
+
export default Throttler;
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Retainer (`time-queues/Retainer.js`)
|
|
282
|
+
|
|
283
|
+
Resource lifecycle management with reference counting.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
interface RetainerOptions<T = unknown> {
|
|
287
|
+
create: () => Promise<T> | T;
|
|
288
|
+
destroy: (value: T) => Promise<void> | void;
|
|
289
|
+
retentionPeriod: number;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
class Retainer<T = unknown> implements RetainerOptions<T> {
|
|
293
|
+
counter: number;
|
|
294
|
+
value: T | null;
|
|
295
|
+
create: () => Promise<T> | T;
|
|
296
|
+
destroy: (value: T) => Promise<void> | void;
|
|
297
|
+
retentionPeriod: number;
|
|
298
|
+
constructor(options: RetainerOptions<T>);
|
|
299
|
+
async get(): Promise<T>;
|
|
300
|
+
async release(immediately?: boolean): Promise<this>;
|
|
301
|
+
}
|
|
302
|
+
export default Retainer;
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### sleep (`time-queues/sleep.js`)
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
function sleep(ms: number | Date): Promise<void>;
|
|
309
|
+
export default sleep;
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### defer (`time-queues/defer.js`)
|
|
313
|
+
|
|
314
|
+
Next-tick execution via `requestIdleCallback` / `setImmediate` / `setTimeout`.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
function defer<A extends unknown[]>(fn: (...args: A) => void): (...args: A) => void;
|
|
318
|
+
function scheduleDefer<R>(fn: () => R): Promise<Awaited<R>>;
|
|
319
|
+
function scheduleDefer(fn: null | undefined): Promise<void>;
|
|
320
|
+
export default defer;
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### throttle (`time-queues/throttle.js`)
|
|
324
|
+
|
|
325
|
+
Execute immediately, ignore calls until timeout expires. Uses first seen args.
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
function throttle<A extends unknown[]>(fn: (...args: A) => void, ms: number): (...args: A) => void;
|
|
329
|
+
export default throttle;
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### debounce (`time-queues/debounce.js`)
|
|
333
|
+
|
|
334
|
+
Delay until input stabilizes. Each call resets the timeout. Uses last seen args.
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
function debounce<A extends unknown[]>(fn: (...args: A) => void, ms: number): (...args: A) => void;
|
|
338
|
+
export default debounce;
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### sample (`time-queues/sample.js`)
|
|
342
|
+
|
|
343
|
+
Execute at regular intervals with last seen args. Intervals never reset and never stop.
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
function sample<A extends unknown[]>(fn: (...args: A) => void, ms: number): (...args: A) => void;
|
|
347
|
+
export default sample;
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### audit (`time-queues/audit.js`)
|
|
351
|
+
|
|
352
|
+
First call starts timeout, then executes with last seen args. Similar to throttle but uses last args.
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
function audit<A extends unknown[]>(fn: (...args: A) => void, ms: number): (...args: A) => void;
|
|
356
|
+
export default audit;
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### batch (`time-queues/batch.js`)
|
|
360
|
+
|
|
361
|
+
Run async operations with concurrency limit. Modeled after `Promise.all()`.
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
function batch(
|
|
365
|
+
fns: ((() => PromiseLike<unknown>) | PromiseLike<unknown> | unknown)[],
|
|
366
|
+
limit?: number // default: 4
|
|
367
|
+
): Promise<unknown[]>;
|
|
368
|
+
export default batch;
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### random-dist (`time-queues/random-dist.js`)
|
|
372
|
+
|
|
373
|
+
Random number distributions.
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
function uniform(min: number, max: number): number;
|
|
377
|
+
function normal(mean: number, stdDev: number, skewness?: number): number;
|
|
378
|
+
function expo(lambda: number): number;
|
|
379
|
+
function pareto(min: number, alpha: number): number;
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### random-sleep (`time-queues/random-sleep.js`)
|
|
383
|
+
|
|
384
|
+
Randomized delays from various distributions. Each factory returns `() => Promise<void>`.
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
type RandomSleepFunction = () => Promise<void>;
|
|
388
|
+
|
|
389
|
+
function randomUniformSleep(min: number, max: number): RandomSleepFunction;
|
|
390
|
+
function randomNormalSleep(mean: number, stdDev: number, skewness?: number): RandomSleepFunction;
|
|
391
|
+
function randomExpoSleep(rate: number, range: number, base?: number): RandomSleepFunction;
|
|
392
|
+
function randomParetoSleep(min: number, ratio?: number): RandomSleepFunction;
|
|
393
|
+
function randomSleep(max: number, min?: number): Promise<void>;
|
|
394
|
+
export default randomSleep;
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### whenDomLoaded (`time-queues/when-dom-loaded.js`)
|
|
398
|
+
|
|
399
|
+
```ts
|
|
400
|
+
function whenDomLoaded(fn: () => void): void;
|
|
401
|
+
function remove(fn: () => void): boolean;
|
|
402
|
+
function scheduleWhenDomLoaded<R>(fn: () => R): Promise<Awaited<R>>;
|
|
403
|
+
function scheduleWhenDomLoaded(fn?: null): Promise<void>;
|
|
404
|
+
export default whenDomLoaded;
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### whenLoaded (`time-queues/when-loaded.js`)
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
function whenLoaded(fn: () => void): void;
|
|
411
|
+
function remove(fn: () => void): boolean;
|
|
412
|
+
function scheduleWhenLoaded<R>(fn: () => R): Promise<Awaited<R>>;
|
|
413
|
+
function scheduleWhenLoaded(fn?: null): Promise<void>;
|
|
414
|
+
export default whenLoaded;
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Key concepts
|
|
418
|
+
|
|
419
|
+
- All modules are **ESM** with `import ... from 'time-queues/<module>.js'`.
|
|
420
|
+
- **Inheritance**: `MicroTaskQueue` → `ListQueue` → specialized queues. `Scheduler` extends `MicroTaskQueue` directly (uses min-heap, not linked list).
|
|
421
|
+
- **Lazy promises** — only created when `.makePromise()` is called or via `schedule()`.
|
|
422
|
+
- **Clean cancellation** — all tasks support cancellation via `CancelTaskError`.
|
|
423
|
+
- **Graceful degradation** — feature detection for browser APIs, works in Node.js/Bun/Deno.
|
|
424
|
+
- **Callback signatures** — queue callbacks receive a destructured context object: `({task, scheduler})` for Scheduler, `({deadline, task, queue})` for IdleQueue, `({timeStamp, task, queue})` for FrameQueue, `(state, prevState, task, queue)` for PageWatcher.
|
|
425
|
+
|
|
426
|
+
## Links
|
|
427
|
+
|
|
428
|
+
- Docs: https://github.com/uhop/time-queues/wiki
|
|
429
|
+
- npm: https://www.npmjs.com/package/time-queues
|
|
430
|
+
- Summary: https://github.com/uhop/time-queues/blob/master/llms.txt
|