time-queues 1.2.4 → 1.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/README.md +76 -6
- package/package.json +10 -7
- package/src/CancelTaskError.d.ts +1 -1
- package/src/CancelTaskError.js +2 -2
- package/src/Counter.d.ts +0 -1
- package/src/LimitedQueue.d.ts +104 -0
- package/src/LimitedQueue.js +78 -0
- package/src/ListQueue.d.ts +0 -5
- package/src/MicroTask.d.ts +2 -1
- package/src/MicroTask.js +30 -15
- package/src/MicroTaskQueue.d.ts +23 -19
- package/src/MicroTaskQueue.js +5 -4
- package/src/Scheduler.d.ts +19 -14
- package/src/batch.d.ts +16 -0
- package/src/batch.js +41 -0
- 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/sleep.d.ts +1 -1
- package/src/throttle.d.ts +2 -1
- package/src/when-dom-loaded.d.ts +4 -8
- package/src/when-dom-loaded.js +3 -7
- package/src/when-loaded.d.ts +4 -8
- package/src/when-loaded.js +3 -7
package/README.md
CHANGED
|
@@ -29,16 +29,21 @@ cd time-queues
|
|
|
29
29
|
npm install
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Documentation
|
|
33
33
|
|
|
34
|
-
The
|
|
34
|
+
The [project wiki](https://github.com/uhop/time-queues/wiki) provides comprehensive information about the `time-queues` library.
|
|
35
35
|
|
|
36
|
-
###
|
|
36
|
+
### Core Task Queue Classes
|
|
37
37
|
|
|
38
|
-
- [
|
|
39
|
-
- [
|
|
38
|
+
- [MicroTask](https://github.com/uhop/time-queues/wiki/MicroTask): Base class for deferred execution
|
|
39
|
+
- [MicroTaskQueue](https://github.com/uhop/time-queues/wiki/MicroTaskQueue): Base class for task queues
|
|
40
|
+
- [ListQueue](https://github.com/uhop/time-queues/wiki/ListQueue): List-based queue implementation
|
|
41
|
+
|
|
42
|
+
### Concurrency Control
|
|
43
|
+
|
|
44
|
+
- [LimitedQueue](https://github.com/uhop/time-queues/wiki/LimitedQueue): Queue with controlled concurrency
|
|
40
45
|
- [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
|
|
46
|
+
- [Counter](https://github.com/uhop/time-queues/wiki/Counter): Track pending task counts
|
|
42
47
|
|
|
43
48
|
### Browser-Specific Components
|
|
44
49
|
|
|
@@ -46,6 +51,11 @@ The full documentation is available in the project's [wiki](https://github.com/u
|
|
|
46
51
|
- [FrameQueue](https://github.com/uhop/time-queues/wiki/FrameQueue): Execute tasks during animation frames
|
|
47
52
|
- [PageWatcher](https://github.com/uhop/time-queues/wiki/PageWatcher): Monitor and respond to page lifecycle changes
|
|
48
53
|
|
|
54
|
+
### Scheduling & Timing
|
|
55
|
+
|
|
56
|
+
- [Scheduler](https://github.com/uhop/time-queues/wiki/Scheduler): Time-based task scheduling
|
|
57
|
+
- [Retainer](https://github.com/uhop/time-queues/wiki/Retainer): Resource lifecycle management
|
|
58
|
+
|
|
49
59
|
### Utility Functions
|
|
50
60
|
|
|
51
61
|
- [defer()](<https://github.com/uhop/time-queues/wiki/defer()>): Execute tasks in the next tick
|
|
@@ -54,6 +64,65 @@ The full documentation is available in the project's [wiki](https://github.com/u
|
|
|
54
64
|
- [debounce()](<https://github.com/uhop/time-queues/wiki/debounce()>): Delay function execution until input stabilizes
|
|
55
65
|
- [sample()](<https://github.com/uhop/time-queues/wiki/sample()>): Execute function at regular intervals
|
|
56
66
|
- [audit()](<https://github.com/uhop/time-queues/wiki/audit()>): Execute function after specified delay
|
|
67
|
+
- [batch()](<https://github.com/uhop/time-queues/wiki/batch()>): Execute async operations with controlled concurrency
|
|
68
|
+
|
|
69
|
+
### Random Distribution Utilities
|
|
70
|
+
|
|
71
|
+
- [random-dist](https://github.com/uhop/time-queues/wiki/random-dist): Generate random numbers from various probability distributions
|
|
72
|
+
- [random-sleep](https://github.com/uhop/time-queues/wiki/random-sleep): Create randomized delays with various probability distributions
|
|
73
|
+
|
|
74
|
+
## Getting Started
|
|
75
|
+
|
|
76
|
+
To get started with `time-queues`, install it via npm:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npm install time-queues
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then import the components you need in your project:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
// Import specific components
|
|
86
|
+
import {Scheduler, repeat} from 'time-queues/Scheduler.js';
|
|
87
|
+
import idleQueue from 'time-queues/IdleQueue.js';
|
|
88
|
+
import defer from 'time-queues/defer.js';
|
|
89
|
+
|
|
90
|
+
// Use the components in your application
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
For more information, see the documentation for each component in the wiki.
|
|
94
|
+
|
|
95
|
+
## Browser-related notes
|
|
96
|
+
|
|
97
|
+
Internally it uses `list-toolkit` and leverages the following browser APIs:
|
|
98
|
+
|
|
99
|
+
- [requestIdleCallback()](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)
|
|
100
|
+
- [requestAnimationFrame()](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
|
|
101
|
+
- [queueMicrotask()](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
|
102
|
+
- [setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
|
|
103
|
+
- Various events and properties.
|
|
104
|
+
|
|
105
|
+
There are many articles on the subject that detail how to leverage the APIs writing efficient applications.
|
|
106
|
+
Some of them are:
|
|
107
|
+
|
|
108
|
+
- [Background Tasks API](https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API)
|
|
109
|
+
- [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API)
|
|
110
|
+
- [Page Lifecycle API](https://developer.chrome.com/docs/web-platform/page-lifecycle-api)
|
|
111
|
+
|
|
112
|
+
This package eliminates the need to write code that you'll write anyway following best practices.
|
|
113
|
+
|
|
114
|
+
### Running a test web application
|
|
115
|
+
|
|
116
|
+
Don't forget to look at a test web application that uses the library. For that you should start a server:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
npm start
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
And navigate to [http://localhost:3000/tests/web/](http://localhost:3000/tests/web/) —
|
|
123
|
+
don't forget to open the console and play around: switch tabs, make other window active,
|
|
124
|
+
navigate away and come back, and so on.
|
|
125
|
+
See how queues work in [tests/web/test.js](https://github.com/uhop/time-queues/blob/main/tests/web/test.js).
|
|
57
126
|
|
|
58
127
|
## License
|
|
59
128
|
|
|
@@ -61,6 +130,7 @@ This project is licensed under the BSD-3-Clause License.
|
|
|
61
130
|
|
|
62
131
|
## Release History
|
|
63
132
|
|
|
133
|
+
- 1.3.0 _Added `batch()` and `LimitedQueue` to run asynchronous operations with controlled concurrency, random distribuitions and random sleep functions, updated dependencies, minor improvements._
|
|
64
134
|
- 1.2.4 _Updated dependencies._
|
|
65
135
|
- 1.2.3 _Updated dependencies._
|
|
66
136
|
- 1.2.2 _`Counter`: separated old waiter from new waiters before notifying them._
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "time-queues",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Time queues to organize multitasking and scheduled tasks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
"test:bun": "tape6-bun --flags FO",
|
|
13
13
|
"test:deno": "tape6-deno --flags FO",
|
|
14
14
|
"test:proc": "tape6-proc --flags FO",
|
|
15
|
-
"test:proc:bun": "bun run `
|
|
16
|
-
"test:proc:deno": "deno run -A `
|
|
15
|
+
"test:proc:bun": "bun run `tape6-proc --self` --flags FO",
|
|
16
|
+
"test:proc:deno": "deno run -A `tape6-proc --self` --flags FO -r -A",
|
|
17
|
+
"test:seq": "tape6-seq --flags FO",
|
|
18
|
+
"test:seq:bun": "bun run `tape6-seq --self` --flags FO",
|
|
19
|
+
"test:seq:deno": "deno run -A `tape6-seq --self` --flags FO",
|
|
17
20
|
"ts-check": "tsc --noEmit",
|
|
18
21
|
"ts-test": "tape6 --flags FO '/ts-tests/test-*.*ts'",
|
|
19
22
|
"ts-test:bun": "tape6-bun --flags FO '/ts-tests/test-*.*ts'",
|
|
@@ -56,12 +59,12 @@
|
|
|
56
59
|
}
|
|
57
60
|
},
|
|
58
61
|
"devDependencies": {
|
|
59
|
-
"@types/node": "^25.
|
|
60
|
-
"tape-six": "^1.
|
|
61
|
-
"tape-six-proc": "^1.
|
|
62
|
+
"@types/node": "^25.2.3",
|
|
63
|
+
"tape-six": "^1.7.0",
|
|
64
|
+
"tape-six-proc": "^1.2.2",
|
|
62
65
|
"typescript": "^5.9.3"
|
|
63
66
|
},
|
|
64
67
|
"dependencies": {
|
|
65
|
-
"list-toolkit": "^2.2.
|
|
68
|
+
"list-toolkit": "^2.2.6"
|
|
66
69
|
}
|
|
67
70
|
}
|
package/src/CancelTaskError.d.ts
CHANGED
package/src/CancelTaskError.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
export class CancelTaskError extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(
|
|
6
|
+
constructor(message = 'Task was canceled', options) {
|
|
7
|
+
super(message, options);
|
|
8
8
|
this.name = 'CancelTaskError';
|
|
9
9
|
if (Error.captureStackTrace) {
|
|
10
10
|
Error.captureStackTrace(this, CancelTaskError);
|
package/src/Counter.d.ts
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {ListQueue, Task} from './ListQueue';
|
|
2
|
+
|
|
3
|
+
export {Task};
|
|
4
|
+
|
|
5
|
+
export declare class LimitedQueue extends ListQueue {
|
|
6
|
+
/**
|
|
7
|
+
* Whether the queue is paused.
|
|
8
|
+
*/
|
|
9
|
+
paused: boolean;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The function that stops the queue.
|
|
13
|
+
* It is used internally by `pause()` and `resume()`.
|
|
14
|
+
*/
|
|
15
|
+
stopQueue: (() => void) | null;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new list queue.
|
|
19
|
+
* @param limit The maximum number of tasks that can be run in parallel.
|
|
20
|
+
* @param paused Whether the queue should start paused.
|
|
21
|
+
*/
|
|
22
|
+
constructor(limit: number, paused?: boolean);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Whether the queue is empty.
|
|
26
|
+
*/
|
|
27
|
+
get isEmpty(): boolean;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the maximum number of tasks that can be run in parallel.
|
|
31
|
+
*/
|
|
32
|
+
get taskLimit(): number;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Set the maximum number of tasks that can be run in parallel.
|
|
36
|
+
* @param limit The new maximum number of tasks that can be run in parallel. It can dynamically add more tasks if the current number of tasks is less than the new limit.
|
|
37
|
+
*/
|
|
38
|
+
set taskLimit(limit: number);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the number of currently active tasks.
|
|
42
|
+
*/
|
|
43
|
+
get activeTasks(): number;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether the queue is idle.
|
|
47
|
+
*/
|
|
48
|
+
get isIdle(): boolean;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Wait for queue to become idle.
|
|
52
|
+
* @returns A promise that resolves when the queue becomes idle. If the queue is already idle, the promise is resolved immediately.
|
|
53
|
+
*/
|
|
54
|
+
waitForIdle(): Promise<void>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Enqueues a microtask.
|
|
58
|
+
* @param fn The function to execute when the microtask is scheduled.
|
|
59
|
+
* @returns The enqueued microtask.
|
|
60
|
+
*/
|
|
61
|
+
enqueue(fn: () => unknown): Task;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Dequeues a microtask.
|
|
65
|
+
* @param task The microtask to dequeue.
|
|
66
|
+
* @returns The queue.
|
|
67
|
+
*/
|
|
68
|
+
dequeue(task: Task): this;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Schedules a microtask.
|
|
72
|
+
* @param fn The function to execute. If `undefined` or `null`, the task's promise will be resolved with function's arguments. Otherwise, it is resolved with the function's return value.
|
|
73
|
+
* @returns The task object.
|
|
74
|
+
*/
|
|
75
|
+
schedule(fn: (() => unknown) | null | undefined): Task;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Clears the queue.
|
|
79
|
+
* @returns The queue.
|
|
80
|
+
*/
|
|
81
|
+
clear(): this;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Pauses the queue.
|
|
85
|
+
* @returns The queue.
|
|
86
|
+
*/
|
|
87
|
+
pause(): this;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resumes the queue.
|
|
91
|
+
* @returns The queue.
|
|
92
|
+
*/
|
|
93
|
+
resume(): this;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Starts the queue.
|
|
97
|
+
* It is used internally by `resume()`.
|
|
98
|
+
* It is meant to be overridden in subclasses.
|
|
99
|
+
* @returns The function that stops the queue.
|
|
100
|
+
*/
|
|
101
|
+
startQueue(): (() => void) | null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default LimitedQueue;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// @ts-self-types="./LimitedQueue.d.ts"
|
|
2
|
+
|
|
3
|
+
import ListQueue from './ListQueue.js';
|
|
4
|
+
|
|
5
|
+
export class LimitedQueue extends ListQueue {
|
|
6
|
+
#taskLimit;
|
|
7
|
+
#activeTasks;
|
|
8
|
+
#idleWaiters;
|
|
9
|
+
|
|
10
|
+
constructor(limit, paused) {
|
|
11
|
+
super(paused);
|
|
12
|
+
this.#taskLimit = limit;
|
|
13
|
+
this.#activeTasks = 0;
|
|
14
|
+
this.#idleWaiters = [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get taskLimit() {
|
|
18
|
+
return this.#taskLimit;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
set taskLimit(limit) {
|
|
22
|
+
this.#taskLimit = Math.max(1, limit);
|
|
23
|
+
this.#processTasks();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get activeTasks() {
|
|
27
|
+
return this.#activeTasks;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get isIdle() {
|
|
31
|
+
return !this.#activeTasks && this.list.isEmpty;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
waitForIdle() {
|
|
35
|
+
return new Promise(resolve => {
|
|
36
|
+
if (this.isIdle) {
|
|
37
|
+
resolve();
|
|
38
|
+
} else {
|
|
39
|
+
this.#idleWaiters.push(resolve);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
startQueue() {
|
|
45
|
+
this.#processTasks();
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#processTasks() {
|
|
50
|
+
if (this.paused) return;
|
|
51
|
+
if (this.isIdle) {
|
|
52
|
+
const waiters = this.#idleWaiters;
|
|
53
|
+
this.#idleWaiters = [];
|
|
54
|
+
waiters.forEach(resolve => resolve());
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
while (this.#activeTasks < this.#taskLimit && !this.list.isEmpty) {
|
|
58
|
+
const task = this.list.popFront();
|
|
59
|
+
++this.#activeTasks;
|
|
60
|
+
LimitedQueue.wrap(() => task.fn({task, queue: this})).finally(() => {
|
|
61
|
+
--this.#activeTasks;
|
|
62
|
+
this.#processTasks();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static wrap(fn) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
try {
|
|
70
|
+
resolve(fn());
|
|
71
|
+
} catch (error) {
|
|
72
|
+
reject(error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default LimitedQueue;
|
package/src/ListQueue.d.ts
CHANGED
package/src/MicroTask.d.ts
CHANGED
|
@@ -42,9 +42,10 @@ export declare class MicroTask {
|
|
|
42
42
|
* Cancels the microtask, if a promise is created.
|
|
43
43
|
* If the microtask is canceled, the promise will be rejected with a CancelTaskError.
|
|
44
44
|
* It can be overridden in subclasses.
|
|
45
|
+
* @param error The optional error to use as the cause of the cancellation.
|
|
45
46
|
* @returns The microtask.
|
|
46
47
|
*/
|
|
47
|
-
cancel(): this;
|
|
48
|
+
cancel(error?: Error): this;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export default MicroTask;
|
package/src/MicroTask.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// @ts-self-types="./MicroTask.d.ts"
|
|
2
2
|
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
3
|
import CancelTaskError from './CancelTaskError.js';
|
|
6
4
|
|
|
7
5
|
export class MicroTask {
|
|
8
6
|
#promise;
|
|
9
7
|
#resolve;
|
|
10
8
|
#reject;
|
|
9
|
+
#settled;
|
|
11
10
|
constructor(fn) {
|
|
12
11
|
this.fn = fn;
|
|
13
12
|
this.#promise = null;
|
|
@@ -18,26 +17,42 @@ export class MicroTask {
|
|
|
18
17
|
get promise() {
|
|
19
18
|
return this.#promise;
|
|
20
19
|
}
|
|
20
|
+
get settled() {
|
|
21
|
+
return this.#settled;
|
|
22
|
+
}
|
|
21
23
|
makePromise() {
|
|
22
|
-
this.#promise
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (this.#promise) return this;
|
|
25
|
+
if (typeof Promise.withResolvers == 'function') {
|
|
26
|
+
({
|
|
27
|
+
promise: this.#promise,
|
|
28
|
+
resolve: this.#resolve,
|
|
29
|
+
reject: this.#reject
|
|
30
|
+
} = Promise.withResolvers());
|
|
31
|
+
} else {
|
|
32
|
+
this.#promise = new Promise((resolve, reject) => {
|
|
33
|
+
this.#resolve = resolve;
|
|
34
|
+
this.#reject = reject;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
26
37
|
return this;
|
|
27
38
|
}
|
|
28
39
|
resolve(value) {
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
if (this.#resolve) {
|
|
41
|
+
this.#resolve(value);
|
|
42
|
+
this.#resolve = null;
|
|
43
|
+
this.#reject = null;
|
|
44
|
+
this.#settled = true;
|
|
45
|
+
}
|
|
33
46
|
return this;
|
|
34
47
|
}
|
|
35
|
-
cancel() {
|
|
36
|
-
if (!this.#reject) return;
|
|
48
|
+
cancel(error) {
|
|
37
49
|
this.isCanceled = true;
|
|
38
|
-
this.#reject
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
if (this.#reject) {
|
|
51
|
+
this.#reject(new CancelTaskError(undefined, error ? {cause: error} : undefined));
|
|
52
|
+
this.#resolve = null;
|
|
53
|
+
this.#reject = null;
|
|
54
|
+
this.#settled = true;
|
|
55
|
+
}
|
|
41
56
|
return this;
|
|
42
57
|
}
|
|
43
58
|
}
|
package/src/MicroTaskQueue.d.ts
CHANGED
|
@@ -2,68 +2,72 @@ import MicroTask from './MicroTask';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* A queue of microtasks that will be executed when scheduled.
|
|
5
|
-
* It
|
|
5
|
+
* It serves as a base class for other task queues.
|
|
6
6
|
*/
|
|
7
7
|
export declare class MicroTaskQueue {
|
|
8
8
|
/**
|
|
9
|
-
* Whether the queue is paused.
|
|
9
|
+
* Whether the queue is currently paused.
|
|
10
|
+
* When paused, new tasks are queued but not executed immediately.
|
|
10
11
|
*/
|
|
11
12
|
paused: boolean;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Creates a new microtask queue.
|
|
15
|
-
* @param paused Whether the queue should start paused.
|
|
16
|
+
* @param paused Whether the queue should start in a paused state.
|
|
16
17
|
*/
|
|
17
18
|
constructor(paused?: boolean);
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Whether the queue is empty.
|
|
21
|
-
*
|
|
22
|
+
* This property should be overridden in subclasses to provide actual implementation.
|
|
22
23
|
*/
|
|
23
24
|
get isEmpty(): boolean;
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
|
-
* Enqueues a microtask.
|
|
27
|
-
*
|
|
27
|
+
* Enqueues a microtask for execution.
|
|
28
|
+
* This method should be overridden in subclasses to provide actual implementation.
|
|
28
29
|
* @param fn The function to execute when the microtask is scheduled.
|
|
29
30
|
* @returns The enqueued microtask.
|
|
30
31
|
*/
|
|
31
32
|
enqueue(fn: () => unknown): MicroTask;
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
|
-
* Dequeues a microtask.
|
|
35
|
-
*
|
|
35
|
+
* Dequeues a microtask from the queue.
|
|
36
|
+
* This method should be overridden in subclasses to provide actual implementation.
|
|
36
37
|
* @param task The microtask to dequeue.
|
|
37
|
-
* @returns The queue.
|
|
38
|
+
* @returns The queue instance for chaining.
|
|
38
39
|
*/
|
|
39
40
|
dequeue(task: MicroTask): this;
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
|
-
* Schedules a microtask with a promise.
|
|
43
|
-
*
|
|
43
|
+
* Schedules a microtask with a promise for execution.
|
|
44
|
+
* This can be overridden in subclasses if more arguments are needed.
|
|
44
45
|
* @param fn The function to execute when the microtask is scheduled, it can be an async function.
|
|
46
|
+
* @param args Additional arguments to pass to `enqueue()`. It is there to accommodate custom implementations in subclasses.
|
|
45
47
|
* @returns The scheduled microtask.
|
|
46
48
|
*/
|
|
47
|
-
schedule(fn: (() => unknown) | null | undefined): MicroTask;
|
|
49
|
+
schedule(fn: (() => unknown) | null | undefined, ...args: unknown[]): MicroTask;
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
|
-
* Clears the queue.
|
|
51
|
-
*
|
|
52
|
-
* @returns The queue.
|
|
52
|
+
* Clears all tasks from the queue.
|
|
53
|
+
* This method should be overridden in subclasses to provide actual implementation.
|
|
54
|
+
* @returns The queue instance for chaining.
|
|
53
55
|
*/
|
|
54
56
|
clear(): this;
|
|
55
57
|
|
|
56
58
|
/**
|
|
57
59
|
* Pauses the queue.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
+
* When paused, new tasks are queued but not executed immediately.
|
|
61
|
+
* This method should be overridden in subclasses to provide actual implementation.
|
|
62
|
+
* @returns The queue instance for chaining.
|
|
60
63
|
*/
|
|
61
64
|
pause(): this;
|
|
62
65
|
|
|
63
66
|
/**
|
|
64
67
|
* Resumes the queue.
|
|
65
|
-
*
|
|
66
|
-
*
|
|
68
|
+
* When resumed, queued tasks will be executed according to their scheduling.
|
|
69
|
+
* This method should be overridden in subclasses to provide actual implementation.
|
|
70
|
+
* @returns The queue instance for chaining.
|
|
67
71
|
*/
|
|
68
72
|
resume(): this;
|
|
69
73
|
}
|
package/src/MicroTaskQueue.js
CHANGED
|
@@ -35,17 +35,18 @@ export class MicroTaskQueue {
|
|
|
35
35
|
schedule(fn, ...args) {
|
|
36
36
|
fn ||= MicroTaskQueue.returnArgs;
|
|
37
37
|
const task = this.enqueue(
|
|
38
|
-
(...args)
|
|
38
|
+
function (...args) {
|
|
39
|
+
this.makePromise();
|
|
39
40
|
try {
|
|
40
|
-
|
|
41
|
+
this.resolve(fn(...args));
|
|
41
42
|
} catch (error) {
|
|
42
|
-
|
|
43
|
+
this.cancel(error);
|
|
43
44
|
}
|
|
45
|
+
return this.promise;
|
|
44
46
|
},
|
|
45
47
|
...args
|
|
46
48
|
);
|
|
47
49
|
task.makePromise();
|
|
48
|
-
task.fn = fn;
|
|
49
50
|
return task;
|
|
50
51
|
}
|
|
51
52
|
static returnArgs(...args) {
|
package/src/Scheduler.d.ts
CHANGED
|
@@ -55,7 +55,6 @@ export declare class Task extends MicroTask {
|
|
|
55
55
|
/**
|
|
56
56
|
* Cancels the microtask, if a promise is created.
|
|
57
57
|
* If the microtask is canceled, the promise will be rejected with a CancelTaskError.
|
|
58
|
-
* It can be overridden in subclasses.
|
|
59
58
|
* @returns The microtask.
|
|
60
59
|
*/
|
|
61
60
|
cancel(): this;
|
|
@@ -67,43 +66,47 @@ export declare class Task extends MicroTask {
|
|
|
67
66
|
export declare class Scheduler extends MicroTaskQueue {
|
|
68
67
|
/**
|
|
69
68
|
* Whether the scheduler is paused.
|
|
69
|
+
* When paused, new tasks are queued but not executed immediately.
|
|
70
70
|
*/
|
|
71
71
|
paused: boolean;
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
* The tolerance for comparing starting time of tasks.
|
|
75
|
+
* This allows for small timing differences in task execution.
|
|
75
76
|
*/
|
|
76
77
|
tolerance: number;
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
80
|
* Creates a new scheduler.
|
|
80
|
-
* @param paused Whether the scheduler should start paused.
|
|
81
|
-
* @param tolerance The tolerance for comparing starting time of tasks.
|
|
81
|
+
* @param paused Whether the scheduler should start in a paused state.
|
|
82
|
+
* @param tolerance The tolerance for comparing starting time of tasks (default is 4ms).
|
|
82
83
|
*/
|
|
83
|
-
constructor(paused?: boolean, tolerance
|
|
84
|
+
constructor(paused?: boolean, tolerance?: number);
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
87
|
* Whether the scheduler is empty.
|
|
88
|
+
* Returns true if there are no tasks scheduled for execution.
|
|
87
89
|
*/
|
|
88
90
|
get isEmpty(): boolean;
|
|
89
91
|
|
|
90
92
|
/**
|
|
91
93
|
* The next scheduled time or `Infinity` if the scheduler is empty.
|
|
94
|
+
* Represents the time when the next task is scheduled to execute.
|
|
92
95
|
*/
|
|
93
96
|
get nextTime(): number;
|
|
94
97
|
|
|
95
98
|
/**
|
|
96
|
-
* Enqueues a task.
|
|
99
|
+
* Enqueues a task for future execution.
|
|
97
100
|
* @param fn The function to execute.
|
|
98
101
|
* @param delay The delay before the task is executed. It can be a number of milliseconds or a `Date` object as an absolute time.
|
|
99
|
-
* @returns The task object.
|
|
102
|
+
* @returns The task object that was enqueued.
|
|
100
103
|
*/
|
|
101
104
|
enqueue(fn: ({task: Task, scheduler: Scheduler}) => unknown, delay: number | Date): Task;
|
|
102
105
|
|
|
103
106
|
/**
|
|
104
107
|
* Removes a task from the scheduler.
|
|
105
108
|
* @param task The task to remove.
|
|
106
|
-
* @returns The scheduler object.
|
|
109
|
+
* @returns The scheduler object for chaining.
|
|
107
110
|
*/
|
|
108
111
|
dequeue(task: Task): this;
|
|
109
112
|
|
|
@@ -111,7 +114,7 @@ export declare class Scheduler extends MicroTaskQueue {
|
|
|
111
114
|
* Schedules a task to run in the future.
|
|
112
115
|
* @param fn The function to execute. If `undefined` or `null`, the task's promise will be resolved with function's arguments. Otherwise, it is resolved with the function's return value.
|
|
113
116
|
* @param delay The delay before the task is executed. It can be a number of milliseconds or a `Date` object as an absolute time.
|
|
114
|
-
* @returns The task object.
|
|
117
|
+
* @returns The task object that was scheduled.
|
|
115
118
|
*/
|
|
116
119
|
schedule(
|
|
117
120
|
fn: (({task: Task, scheduler: Scheduler}) => unknown) | null | undefined,
|
|
@@ -119,20 +122,22 @@ export declare class Scheduler extends MicroTaskQueue {
|
|
|
119
122
|
): Task;
|
|
120
123
|
|
|
121
124
|
/**
|
|
122
|
-
* Clears the
|
|
123
|
-
* @returns The
|
|
125
|
+
* Clears all tasks from the scheduler.
|
|
126
|
+
* @returns The scheduler instance for chaining.
|
|
124
127
|
*/
|
|
125
128
|
clear(): this;
|
|
126
129
|
|
|
127
130
|
/**
|
|
128
|
-
* Pauses the
|
|
129
|
-
*
|
|
131
|
+
* Pauses the scheduler.
|
|
132
|
+
* When paused, new tasks are queued but not executed immediately.
|
|
133
|
+
* @returns The scheduler instance for chaining.
|
|
130
134
|
*/
|
|
131
135
|
pause(): this;
|
|
132
136
|
|
|
133
137
|
/**
|
|
134
|
-
* Resumes the
|
|
135
|
-
*
|
|
138
|
+
* Resumes the scheduler.
|
|
139
|
+
* When resumed, queued tasks will be executed according to their scheduling.
|
|
140
|
+
* @returns The scheduler instance for chaining.
|
|
136
141
|
*/
|
|
137
142
|
resume(): this;
|
|
138
143
|
}
|
package/src/batch.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs asynchronous operations in parallel, no more than a specified number at a time.
|
|
3
|
+
* It takes an array of functions, which return promises when invoked without arguments.
|
|
4
|
+
* All other non-function values are passed as-is and promises are resolved.
|
|
5
|
+
* Modelled after Promise.all().
|
|
6
|
+
*
|
|
7
|
+
* @param fns An array of parameterless functions (asynchronous or not), promises, or values
|
|
8
|
+
* @param limit How many asynchronous operations to run in parallel (default is 4)
|
|
9
|
+
* @returns A promise that resolves when all functions have completed to an array of results
|
|
10
|
+
*/
|
|
11
|
+
export declare function batch(
|
|
12
|
+
fns: ((() => PromiseLike<unknown>) | PromiseLike<unknown> | unknown)[],
|
|
13
|
+
limit?: number
|
|
14
|
+
): Promise<unknown[]>;
|
|
15
|
+
|
|
16
|
+
export default batch;
|
package/src/batch.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @ts-self-types="./batch.d.ts"
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const wrap = value => {
|
|
6
|
+
if (typeof value == 'function') return Promise.resolve(value());
|
|
7
|
+
if (value && typeof value.then == 'function') return value; // thenable
|
|
8
|
+
return Promise.resolve(value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const batch = (fns, limit = 4) => {
|
|
12
|
+
if (limit < 1) limit = 1;
|
|
13
|
+
|
|
14
|
+
const result = [];
|
|
15
|
+
let next = limit,
|
|
16
|
+
available = limit;
|
|
17
|
+
|
|
18
|
+
const saveResult = (index, resolve, reject) => value => {
|
|
19
|
+
result[index] = value;
|
|
20
|
+
if (next < fns.length) {
|
|
21
|
+
wrap(fns[next]).then(saveResult(next, resolve, reject), reject);
|
|
22
|
+
++next;
|
|
23
|
+
} else {
|
|
24
|
+
++available;
|
|
25
|
+
if (available === limit) {
|
|
26
|
+
// we are done
|
|
27
|
+
resolve(result);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
// start the pump
|
|
34
|
+
for (let i = 0, n = Math.min(fns.length, limit); i < n; ++i) {
|
|
35
|
+
wrap(fns[i]).then(saveResult(i, resolve, reject), reject);
|
|
36
|
+
--available;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default batch;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a random number from a uniform distribution.
|
|
3
|
+
* @param min The minimum value of the distribution.
|
|
4
|
+
* @param max The maximum value of the distribution.
|
|
5
|
+
* @returns A random number from the uniform distribution.
|
|
6
|
+
*/
|
|
7
|
+
export declare function uniform(min: number, max: number): number;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate a random number from a normal distribution.
|
|
11
|
+
* @param mean The mean of the distribution.
|
|
12
|
+
* @param stdDev The standard deviation of the distribution.
|
|
13
|
+
* @param skewness The skewness of the distribution.
|
|
14
|
+
* @returns A random number from the normal distribution.
|
|
15
|
+
*/
|
|
16
|
+
export declare function normal(mean: number, stdDev: number, skewness: number = 0): number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generate a random number from an exponential distribution.
|
|
20
|
+
* @param lambda The rate parameter of the distribution.
|
|
21
|
+
* @returns A random number from the exponential distribution.
|
|
22
|
+
*/
|
|
23
|
+
export declare function expo(lambda: number): number;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Generate a random number from a Pareto distribution.
|
|
27
|
+
* @param min The minimum value of the distribution.
|
|
28
|
+
* @param alpha The shape parameter of the distribution.
|
|
29
|
+
* @returns A random number from the Pareto distribution.
|
|
30
|
+
*/
|
|
31
|
+
export declare function pareto(min: number, alpha: number): number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @ts-self-types="./random-dist.d.ts"
|
|
2
|
+
|
|
3
|
+
export const uniform = (min, max) => {
|
|
4
|
+
const range = Math.abs(max - min);
|
|
5
|
+
return Math.random() * range + Math.min(min, max);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const normal = (mean, stdDev, skewness = 0) => {
|
|
9
|
+
let u = 0,
|
|
10
|
+
v = 0;
|
|
11
|
+
while (!u) u = Math.random(); // Converting [0,1) to (0,1)
|
|
12
|
+
while (!v) v = Math.random();
|
|
13
|
+
let z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
|
14
|
+
if (!skewness) return z * stdDev + mean;
|
|
15
|
+
const delta = skewness / Math.sqrt(1 + skewness * skewness),
|
|
16
|
+
x = delta * z + Math.sqrt(1 - delta * delta) * v;
|
|
17
|
+
z = z >= 0 ? x : -x;
|
|
18
|
+
return z * stdDev + mean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const expo = lambda => {
|
|
22
|
+
return -Math.log(1 - Math.random()) / lambda;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const pareto = (min, alpha) => {
|
|
26
|
+
return min / Math.pow(1 - Math.random(), 1 / alpha);
|
|
27
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Random sleep function modelled after `sleep()`.
|
|
3
|
+
*/
|
|
4
|
+
export type RandomSleepFunction = () => Promise<void>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a random sleep function that uses a uniform distribution.
|
|
8
|
+
* @param min The minimum delay in milliseconds.
|
|
9
|
+
* @param max The maximum delay in milliseconds.
|
|
10
|
+
* @returns A sleep function.
|
|
11
|
+
*/
|
|
12
|
+
export declare function randomUniformSleep(min: number, max: number): RandomSleepFunction;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a random sleep function that uses a normal distribution.
|
|
16
|
+
* @param mean The mean delay in milliseconds.
|
|
17
|
+
* @param stdDev The standard deviation of the delay in milliseconds.
|
|
18
|
+
* @param skewness The skewness of the delay distribution.
|
|
19
|
+
* @returns A sleep function.
|
|
20
|
+
*/
|
|
21
|
+
export declare function randomNormalSleep(
|
|
22
|
+
mean: number,
|
|
23
|
+
stdDev: number,
|
|
24
|
+
skewness: number = 0
|
|
25
|
+
): RandomSleepFunction;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a random sleep function that uses an exponential distribution.
|
|
29
|
+
* @param rate The rate parameter of the exponential distribution (how many times per `range` an event occurs).
|
|
30
|
+
* @param range The range of the exponential distribution.
|
|
31
|
+
* @param base The base of the exponential distribution.
|
|
32
|
+
* @returns A sleep function.
|
|
33
|
+
*/
|
|
34
|
+
export declare function randomExpoSleep(
|
|
35
|
+
rate: number,
|
|
36
|
+
range: number,
|
|
37
|
+
base: number = 0
|
|
38
|
+
): RandomSleepFunction;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Creates a random sleep function that uses a Pareto distribution.
|
|
42
|
+
* @param min The minimum delay in milliseconds.
|
|
43
|
+
* @param ratio The ratio of the Pareto distribution, e.g., 0.8 for the 80/20 Pareto rule. Should be a value between 0.5 and 1.
|
|
44
|
+
* @returns A sleep function.
|
|
45
|
+
* @throws Error if the ratio is not between 0.5 and 1.
|
|
46
|
+
*/
|
|
47
|
+
export declare function randomParetoSleep(min: number, ratio: number = 0.8): RandomSleepFunction;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A simple sleep function that uses a uniform distribution.
|
|
51
|
+
* @param max The maximum delay in milliseconds.
|
|
52
|
+
* @param min The minimum delay in milliseconds.
|
|
53
|
+
* @returns A promise that resolves after the delay.
|
|
54
|
+
*/
|
|
55
|
+
export declare function randomSleep(max: number, min: number = 0): Promise<void>;
|
|
56
|
+
|
|
57
|
+
export default randomSleep;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @ts-self-types="./random-sleep.d.ts"
|
|
2
|
+
|
|
3
|
+
import sleep from './sleep.js';
|
|
4
|
+
import {uniform, normal, expo, pareto} from './random-dist.js';
|
|
5
|
+
|
|
6
|
+
export const randomUniformSleep = (min, max) => () => sleep(uniform(min, max));
|
|
7
|
+
|
|
8
|
+
export const randomNormalSleep =
|
|
9
|
+
(mean, stdDev, skewness = 0) =>
|
|
10
|
+
() =>
|
|
11
|
+
sleep(normal(mean, stdDev, skewness));
|
|
12
|
+
|
|
13
|
+
export const randomExpoSleep =
|
|
14
|
+
(rate, range, base = 0) =>
|
|
15
|
+
() =>
|
|
16
|
+
sleep(range * expo(rate) + base);
|
|
17
|
+
|
|
18
|
+
export const randomParetoSleep = (min, ratio = 0.8) => {
|
|
19
|
+
if (ratio <= 0.5 || ratio >= 1 || isNaN(ratio))
|
|
20
|
+
throw new Error('ratio must be greater than 0.5 and less than 1');
|
|
21
|
+
const alpha = 1 / (1 - Math.log(ratio) / Math.log(1 - ratio));
|
|
22
|
+
return () => sleep(pareto(min, alpha));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const randomSleep = (max, min = 0) => sleep(uniform(min, max));
|
|
26
|
+
|
|
27
|
+
export default randomSleep;
|
package/src/sleep.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Suspends the execution for a specified time.
|
|
3
3
|
*
|
|
4
|
-
* @param ms The time to suspend the execution for, in milliseconds or a
|
|
4
|
+
* @param ms The time to suspend the execution for, in milliseconds or a Date as an absolute time.
|
|
5
5
|
* @returns A promise that resolves after the specified time.
|
|
6
6
|
*/
|
|
7
7
|
export declare function sleep(ms: number | Date): Promise<void>;
|
package/src/throttle.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Throttles a function by ensuring it is not called more often than the specified interval.
|
|
3
|
-
* The first call calls the function and starts a timeout. Until the timeout expires,
|
|
3
|
+
* The first call calls the function and starts a timeout. Until the timeout expires,
|
|
4
|
+
* any subsequent calls are ignored.
|
|
4
5
|
* This function is similar to `audit()`, but the first seen arguments are passed to the function.
|
|
5
6
|
*
|
|
6
7
|
* @param fn The function to throttle.
|
package/src/when-dom-loaded.d.ts
CHANGED
|
@@ -20,18 +20,14 @@ export declare function remove(fn: () => void): boolean;
|
|
|
20
20
|
* @param fn The function to schedule.
|
|
21
21
|
* @returns A promise that resolves when the DOM is loaded.
|
|
22
22
|
*/
|
|
23
|
-
export declare function scheduleWhenDomLoaded<R extends unknown>(
|
|
24
|
-
fn: () => R
|
|
25
|
-
): Promise<Awaited<R>>;
|
|
23
|
+
export declare function scheduleWhenDomLoaded<R extends unknown>(fn: () => R): Promise<Awaited<R>>;
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
|
-
*
|
|
26
|
+
* Resolves a promise when the DOM is loaded.
|
|
29
27
|
*
|
|
30
|
-
* @param fn
|
|
28
|
+
* @param fn `null` or `undefined`.
|
|
31
29
|
* @returns A promise that resolves when the DOM is loaded.
|
|
32
30
|
*/
|
|
33
|
-
export declare function scheduleWhenDomLoaded(
|
|
34
|
-
fn: null | undefined
|
|
35
|
-
): Promise<void>;
|
|
31
|
+
export declare function scheduleWhenDomLoaded(fn?: null): Promise<void>;
|
|
36
32
|
|
|
37
33
|
export default whenDomLoaded;
|
package/src/when-dom-loaded.js
CHANGED
|
@@ -34,19 +34,15 @@ export const whenDomLoaded = fn => {
|
|
|
34
34
|
if (wasEmpty) document.addEventListener('DOMContentLoaded', handleDomLoaded);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
export const scheduleWhenDomLoaded = fn => {
|
|
40
|
-
fn ||= returnArgs;
|
|
41
|
-
return new Promise((resolve, reject) => {
|
|
37
|
+
export const scheduleWhenDomLoaded = fn =>
|
|
38
|
+
new Promise((resolve, reject) => {
|
|
42
39
|
whenDomLoaded(() => {
|
|
43
40
|
try {
|
|
44
|
-
resolve(fn());
|
|
41
|
+
resolve(fn?.());
|
|
45
42
|
} catch (error) {
|
|
46
43
|
reject(error);
|
|
47
44
|
}
|
|
48
45
|
});
|
|
49
46
|
});
|
|
50
|
-
};
|
|
51
47
|
|
|
52
48
|
export default whenDomLoaded;
|
package/src/when-loaded.d.ts
CHANGED
|
@@ -20,18 +20,14 @@ export declare function remove(fn: () => void): boolean;
|
|
|
20
20
|
* @param fn The function to schedule.
|
|
21
21
|
* @returns A promise that resolves when the document is loaded.
|
|
22
22
|
*/
|
|
23
|
-
export declare function scheduleWhenLoaded<R extends unknown>(
|
|
24
|
-
fn: () => R
|
|
25
|
-
): Promise<Awaited<R>>;
|
|
23
|
+
export declare function scheduleWhenLoaded<R extends unknown>(fn: () => R): Promise<Awaited<R>>;
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
|
-
*
|
|
26
|
+
* Resolves a promise when the document is loaded.
|
|
29
27
|
*
|
|
30
|
-
* @param fn
|
|
28
|
+
* @param fn `null` or `undefined`.
|
|
31
29
|
* @returns A promise that resolves when the document is loaded.
|
|
32
30
|
*/
|
|
33
|
-
export declare function scheduleWhenLoaded(
|
|
34
|
-
fn: null | undefined
|
|
35
|
-
): Promise<void>;
|
|
31
|
+
export declare function scheduleWhenLoaded(fn?: null): Promise<void>;
|
|
36
32
|
|
|
37
33
|
export default whenLoaded;
|
package/src/when-loaded.js
CHANGED
|
@@ -32,19 +32,15 @@ export const whenLoaded = fn => {
|
|
|
32
32
|
if (wasEmpty) window.addEventListener('load', handleLoaded);
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
export const scheduleWhenLoaded = fn => {
|
|
38
|
-
fn ||= returnArgs;
|
|
39
|
-
return new Promise((resolve, reject) => {
|
|
35
|
+
export const scheduleWhenLoaded = fn =>
|
|
36
|
+
new Promise((resolve, reject) => {
|
|
40
37
|
whenLoaded(() => {
|
|
41
38
|
try {
|
|
42
|
-
resolve(fn());
|
|
39
|
+
resolve(fn?.());
|
|
43
40
|
} catch (error) {
|
|
44
41
|
reject(error);
|
|
45
42
|
}
|
|
46
43
|
});
|
|
47
44
|
});
|
|
48
|
-
};
|
|
49
45
|
|
|
50
46
|
export default whenLoaded;
|