@tanstack/pacer 0.8.0 → 0.9.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-batcher.cjs +163 -0
- package/dist/cjs/async-batcher.cjs.map +1 -0
- package/dist/cjs/async-batcher.d.cts +273 -0
- package/dist/cjs/async-debouncer.cjs +149 -162
- package/dist/cjs/async-debouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer.d.cts +76 -57
- package/dist/cjs/async-queuer.cjs +282 -343
- package/dist/cjs/async-queuer.cjs.map +1 -1
- package/dist/cjs/async-queuer.d.cts +121 -100
- package/dist/cjs/async-rate-limiter.cjs +128 -185
- package/dist/cjs/async-rate-limiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter.d.cts +72 -61
- package/dist/cjs/async-throttler.cjs +168 -178
- package/dist/cjs/async-throttler.cjs.map +1 -1
- package/dist/cjs/async-throttler.d.cts +97 -69
- package/dist/cjs/batcher.cjs +110 -119
- package/dist/cjs/batcher.cjs.map +1 -1
- package/dist/cjs/batcher.d.cts +76 -51
- package/dist/cjs/debouncer.cjs +97 -85
- package/dist/cjs/debouncer.cjs.map +1 -1
- package/dist/cjs/debouncer.d.cts +54 -26
- package/dist/cjs/index.cjs +3 -6
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/queuer.cjs +246 -294
- package/dist/cjs/queuer.cjs.map +1 -1
- package/dist/cjs/queuer.d.cts +102 -81
- package/dist/cjs/rate-limiter.cjs +97 -130
- package/dist/cjs/rate-limiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter.d.cts +50 -37
- package/dist/cjs/throttler.cjs +107 -123
- package/dist/cjs/throttler.cjs.map +1 -1
- package/dist/cjs/throttler.d.cts +59 -35
- package/dist/cjs/utils.cjs +0 -13
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +0 -1
- package/dist/esm/async-batcher.d.ts +273 -0
- package/dist/esm/async-batcher.js +163 -0
- package/dist/esm/async-batcher.js.map +1 -0
- package/dist/esm/async-debouncer.d.ts +76 -57
- package/dist/esm/async-debouncer.js +149 -162
- package/dist/esm/async-debouncer.js.map +1 -1
- package/dist/esm/async-queuer.d.ts +121 -100
- package/dist/esm/async-queuer.js +282 -343
- package/dist/esm/async-queuer.js.map +1 -1
- package/dist/esm/async-rate-limiter.d.ts +72 -61
- package/dist/esm/async-rate-limiter.js +128 -185
- package/dist/esm/async-rate-limiter.js.map +1 -1
- package/dist/esm/async-throttler.d.ts +97 -69
- package/dist/esm/async-throttler.js +168 -178
- package/dist/esm/async-throttler.js.map +1 -1
- package/dist/esm/batcher.d.ts +76 -51
- package/dist/esm/batcher.js +110 -119
- package/dist/esm/batcher.js.map +1 -1
- package/dist/esm/debouncer.d.ts +54 -26
- package/dist/esm/debouncer.js +97 -85
- package/dist/esm/debouncer.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +4 -7
- package/dist/esm/queuer.d.ts +102 -81
- package/dist/esm/queuer.js +246 -294
- package/dist/esm/queuer.js.map +1 -1
- package/dist/esm/rate-limiter.d.ts +50 -37
- package/dist/esm/rate-limiter.js +97 -130
- package/dist/esm/rate-limiter.js.map +1 -1
- package/dist/esm/throttler.d.ts +59 -35
- package/dist/esm/throttler.js +107 -123
- package/dist/esm/throttler.js.map +1 -1
- package/dist/esm/utils.d.ts +0 -1
- package/dist/esm/utils.js +0 -13
- package/dist/esm/utils.js.map +1 -1
- package/package.json +14 -11
- package/src/async-batcher.ts +475 -0
- package/src/async-debouncer.ts +201 -121
- package/src/async-queuer.ts +337 -216
- package/src/async-rate-limiter.ts +176 -136
- package/src/async-throttler.ts +233 -139
- package/src/batcher.ts +158 -92
- package/src/debouncer.ts +135 -52
- package/src/index.ts +1 -1
- package/src/queuer.ts +348 -226
- package/src/rate-limiter.ts +125 -80
- package/src/throttler.ts +152 -78
- package/src/utils.ts +0 -15
- package/dist/cjs/compare.cjs +0 -72
- package/dist/cjs/compare.cjs.map +0 -1
- package/dist/cjs/compare.d.cts +0 -12
- package/dist/esm/compare.d.ts +0 -12
- package/dist/esm/compare.js +0 -72
- package/dist/esm/compare.js.map +0 -1
- package/src/compare.ts +0 -105
package/dist/cjs/queuer.cjs
CHANGED
|
@@ -1,325 +1,277 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const store = require("@tanstack/store");
|
|
3
4
|
const utils = require("./utils.cjs");
|
|
5
|
+
function getDefaultQueuerState() {
|
|
6
|
+
return {
|
|
7
|
+
executionCount: 0,
|
|
8
|
+
expirationCount: 0,
|
|
9
|
+
isEmpty: true,
|
|
10
|
+
isFull: false,
|
|
11
|
+
isIdle: true,
|
|
12
|
+
isRunning: true,
|
|
13
|
+
itemTimestamps: [],
|
|
14
|
+
items: [],
|
|
15
|
+
pendingTick: false,
|
|
16
|
+
rejectionCount: 0,
|
|
17
|
+
size: 0,
|
|
18
|
+
status: "idle"
|
|
19
|
+
};
|
|
20
|
+
}
|
|
4
21
|
const defaultOptions = {
|
|
5
22
|
addItemsTo: "back",
|
|
6
23
|
getItemsFrom: "front",
|
|
7
|
-
getPriority: (item) =>
|
|
24
|
+
getPriority: (item) => item?.priority ?? 0,
|
|
8
25
|
getIsExpired: () => false,
|
|
9
26
|
expirationDuration: Infinity,
|
|
10
27
|
initialItems: [],
|
|
11
28
|
maxSize: Infinity,
|
|
12
|
-
onExecute: () => {
|
|
13
|
-
},
|
|
14
|
-
onIsRunningChange: () => {
|
|
15
|
-
},
|
|
16
|
-
onItemsChange: () => {
|
|
17
|
-
},
|
|
18
|
-
onReject: () => {
|
|
19
|
-
},
|
|
20
|
-
onExpire: () => {
|
|
21
|
-
},
|
|
22
29
|
started: true,
|
|
23
30
|
wait: 0
|
|
24
31
|
};
|
|
25
32
|
class Queuer {
|
|
26
33
|
constructor(fn, initialOptions = {}) {
|
|
27
34
|
this.fn = fn;
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* Processes items in the queue up to the wait interval. Internal use only.
|
|
64
|
-
*/
|
|
65
|
-
tick() {
|
|
66
|
-
if (!this._running) {
|
|
67
|
-
this._pendingTick = false;
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this.checkExpiredItems();
|
|
71
|
-
while (!this.getIsEmpty()) {
|
|
72
|
-
const nextItem = this.execute(this._options.getItemsFrom);
|
|
73
|
-
if (nextItem === void 0) {
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
this._onItemsChanges.forEach((cb) => cb(nextItem));
|
|
77
|
-
const wait = this.getWait();
|
|
78
|
-
if (wait > 0) {
|
|
79
|
-
setTimeout(() => this.tick(), wait);
|
|
35
|
+
this.store = new store.Store(
|
|
36
|
+
getDefaultQueuerState()
|
|
37
|
+
);
|
|
38
|
+
this.#timeoutId = null;
|
|
39
|
+
this.setOptions = (newOptions) => {
|
|
40
|
+
this.options = { ...this.options, ...newOptions };
|
|
41
|
+
};
|
|
42
|
+
this.#setState = (newState) => {
|
|
43
|
+
this.store.setState((state) => {
|
|
44
|
+
const combinedState = {
|
|
45
|
+
...state,
|
|
46
|
+
...newState
|
|
47
|
+
};
|
|
48
|
+
const { items, isRunning } = combinedState;
|
|
49
|
+
const size = items.length;
|
|
50
|
+
const isFull = size >= (this.options.maxSize ?? Infinity);
|
|
51
|
+
const isEmpty = size === 0;
|
|
52
|
+
const isIdle = isRunning && isEmpty;
|
|
53
|
+
const status = isIdle ? "idle" : isRunning ? "running" : "stopped";
|
|
54
|
+
return {
|
|
55
|
+
...combinedState,
|
|
56
|
+
isEmpty,
|
|
57
|
+
isFull,
|
|
58
|
+
isIdle,
|
|
59
|
+
size,
|
|
60
|
+
status
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
this.#getWait = () => {
|
|
65
|
+
return utils.parseFunctionOrValue(this.options.wait ?? 0, this);
|
|
66
|
+
};
|
|
67
|
+
this.#tick = () => {
|
|
68
|
+
if (!this.store.state.isRunning) {
|
|
69
|
+
this.#setState({ pendingTick: false });
|
|
80
70
|
return;
|
|
81
71
|
}
|
|
82
|
-
this
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < this._items.length; i++) {
|
|
96
|
-
const timestamp = this._itemTimestamps[i];
|
|
97
|
-
if (timestamp === void 0) continue;
|
|
98
|
-
const item = this._items[i];
|
|
99
|
-
if (item === void 0) continue;
|
|
100
|
-
const isExpired = this._options.getIsExpired !== defaultOptions.getIsExpired ? this._options.getIsExpired(item, timestamp) : now - timestamp > this._options.expirationDuration;
|
|
101
|
-
if (isExpired) {
|
|
102
|
-
expiredIndices.push(i);
|
|
72
|
+
this.#setState({ pendingTick: true });
|
|
73
|
+
this.#checkExpiredItems();
|
|
74
|
+
while (!this.store.state.isEmpty) {
|
|
75
|
+
const nextItem = this.execute(this.options.getItemsFrom ?? "front");
|
|
76
|
+
if (nextItem === void 0) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
const wait = this.#getWait();
|
|
80
|
+
if (wait > 0) {
|
|
81
|
+
this.#timeoutId = setTimeout(() => this.#tick(), wait);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.#tick();
|
|
103
85
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
*/
|
|
130
|
-
start() {
|
|
131
|
-
this._running = true;
|
|
132
|
-
if (!this._pendingTick && !this.getIsEmpty()) {
|
|
133
|
-
this._pendingTick = true;
|
|
134
|
-
this.tick();
|
|
135
|
-
}
|
|
136
|
-
this._options.onIsRunningChange(this);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Removes all pending items from the queue. Does not affect items being processed.
|
|
140
|
-
*/
|
|
141
|
-
clear() {
|
|
142
|
-
this._items = [];
|
|
143
|
-
this._options.onItemsChange(this);
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Resets the queuer to its initial state. Optionally repopulates with initial items.
|
|
147
|
-
* Does not affect callbacks or options.
|
|
148
|
-
*/
|
|
149
|
-
reset(withInitialItems) {
|
|
150
|
-
this.clear();
|
|
151
|
-
this._executionCount = 0;
|
|
152
|
-
if (withInitialItems) {
|
|
153
|
-
this._items = [...this._options.initialItems];
|
|
154
|
-
}
|
|
155
|
-
this._running = this._options.started;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Adds an item to the queue. If the queue is full, the item is rejected and onReject is called.
|
|
159
|
-
* Items can be inserted based on priority or at the front/back depending on configuration.
|
|
160
|
-
*
|
|
161
|
-
* Returns true if the item was added, false if the queue is full.
|
|
162
|
-
*
|
|
163
|
-
* Example usage:
|
|
164
|
-
* ```ts
|
|
165
|
-
* queuer.addItem('task');
|
|
166
|
-
* queuer.addItem('task2', 'front');
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
addItem(item, position = this._options.addItemsTo, runOnUpdate = true) {
|
|
170
|
-
if (this.getIsFull()) {
|
|
171
|
-
this._rejectionCount++;
|
|
172
|
-
this._options.onReject(item, this);
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
if (this._options.getPriority !== defaultOptions.getPriority) {
|
|
176
|
-
const priority = this._options.getPriority(item);
|
|
177
|
-
const insertIndex = this._items.findIndex(
|
|
178
|
-
(existing) => this._options.getPriority(existing) < priority
|
|
179
|
-
);
|
|
180
|
-
if (insertIndex === -1) {
|
|
181
|
-
this._items.push(item);
|
|
182
|
-
this._itemTimestamps.push(Date.now());
|
|
86
|
+
this.#setState({ pendingTick: false });
|
|
87
|
+
};
|
|
88
|
+
this.addItem = (item, position = this.options.addItemsTo ?? "back", runOnItemsChange = true) => {
|
|
89
|
+
if (this.store.state.isFull) {
|
|
90
|
+
this.#setState({
|
|
91
|
+
rejectionCount: this.store.state.rejectionCount + 1
|
|
92
|
+
});
|
|
93
|
+
this.options.onReject?.(item, this);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const priority = this.options.getPriority !== defaultOptions.getPriority ? this.options.getPriority(item) : item.priority;
|
|
97
|
+
const items = this.store.state.items;
|
|
98
|
+
const itemTimestamps = this.store.state.itemTimestamps;
|
|
99
|
+
if (priority !== void 0) {
|
|
100
|
+
const insertIndex = items.findIndex((existing) => {
|
|
101
|
+
const existingPriority = this.options.getPriority !== defaultOptions.getPriority ? this.options.getPriority(existing) : existing.priority;
|
|
102
|
+
return existingPriority < priority;
|
|
103
|
+
});
|
|
104
|
+
if (insertIndex === -1) {
|
|
105
|
+
items.push(item);
|
|
106
|
+
itemTimestamps.push(Date.now());
|
|
107
|
+
} else {
|
|
108
|
+
items.splice(insertIndex, 0, item);
|
|
109
|
+
itemTimestamps.splice(insertIndex, 0, Date.now());
|
|
110
|
+
}
|
|
183
111
|
} else {
|
|
184
|
-
|
|
185
|
-
|
|
112
|
+
if (position === "front") {
|
|
113
|
+
items.unshift(item);
|
|
114
|
+
itemTimestamps.unshift(Date.now());
|
|
115
|
+
} else {
|
|
116
|
+
items.push(item);
|
|
117
|
+
itemTimestamps.push(Date.now());
|
|
118
|
+
}
|
|
186
119
|
}
|
|
187
|
-
|
|
120
|
+
this.#setState({
|
|
121
|
+
items,
|
|
122
|
+
itemTimestamps
|
|
123
|
+
});
|
|
124
|
+
if (runOnItemsChange) {
|
|
125
|
+
this.options.onItemsChange?.(this);
|
|
126
|
+
}
|
|
127
|
+
if (this.store.state.isRunning && !this.store.state.pendingTick) {
|
|
128
|
+
this.#setState({ pendingTick: true });
|
|
129
|
+
this.#tick();
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
};
|
|
133
|
+
this.getNextItem = (position = this.options.getItemsFrom ?? "front") => {
|
|
134
|
+
const { items, itemTimestamps } = this.store.state;
|
|
135
|
+
let item;
|
|
188
136
|
if (position === "front") {
|
|
189
|
-
|
|
190
|
-
|
|
137
|
+
item = items[0];
|
|
138
|
+
if (item !== void 0) {
|
|
139
|
+
this.#setState({
|
|
140
|
+
items: items.slice(1),
|
|
141
|
+
itemTimestamps: itemTimestamps.slice(1)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
191
144
|
} else {
|
|
192
|
-
|
|
193
|
-
|
|
145
|
+
item = items[items.length - 1];
|
|
146
|
+
if (item !== void 0) {
|
|
147
|
+
this.#setState({
|
|
148
|
+
items: items.slice(0, -1),
|
|
149
|
+
itemTimestamps: itemTimestamps.slice(0, -1)
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (item !== void 0) {
|
|
154
|
+
this.options.onItemsChange?.(this);
|
|
155
|
+
}
|
|
156
|
+
return item;
|
|
157
|
+
};
|
|
158
|
+
this.execute = (position) => {
|
|
159
|
+
const item = this.getNextItem(position);
|
|
160
|
+
if (item !== void 0) {
|
|
161
|
+
this.fn(item);
|
|
162
|
+
this.#setState({
|
|
163
|
+
executionCount: this.store.state.executionCount + 1
|
|
164
|
+
});
|
|
165
|
+
this.options.onExecute?.(item, this);
|
|
166
|
+
}
|
|
167
|
+
return item;
|
|
168
|
+
};
|
|
169
|
+
this.flush = (numberOfItems = this.store.state.items.length, position) => {
|
|
170
|
+
this.#clearTimeout();
|
|
171
|
+
for (let i = 0; i < numberOfItems; i++) {
|
|
172
|
+
this.execute(position);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
this.#checkExpiredItems = () => {
|
|
176
|
+
if ((this.options.expirationDuration ?? Infinity) === Infinity && this.options.getIsExpired === defaultOptions.getIsExpired) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const now = Date.now();
|
|
180
|
+
const expiredIndices = [];
|
|
181
|
+
for (let i = 0; i < this.store.state.items.length; i++) {
|
|
182
|
+
const timestamp = this.store.state.itemTimestamps[i];
|
|
183
|
+
if (timestamp === void 0) continue;
|
|
184
|
+
const item = this.store.state.items[i];
|
|
185
|
+
if (item === void 0) continue;
|
|
186
|
+
const isExpired = this.options.getIsExpired !== defaultOptions.getIsExpired ? this.options.getIsExpired(item, timestamp) : now - timestamp > (this.options.expirationDuration ?? Infinity);
|
|
187
|
+
if (isExpired) {
|
|
188
|
+
expiredIndices.push(i);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
for (let i = expiredIndices.length - 1; i >= 0; i--) {
|
|
192
|
+
const index = expiredIndices[i];
|
|
193
|
+
if (index === void 0) continue;
|
|
194
|
+
const expiredItem = this.store.state.items[index];
|
|
195
|
+
if (expiredItem === void 0) continue;
|
|
196
|
+
const newItems = [...this.store.state.items];
|
|
197
|
+
const newTimestamps = [...this.store.state.itemTimestamps];
|
|
198
|
+
newItems.splice(index, 1);
|
|
199
|
+
newTimestamps.splice(index, 1);
|
|
200
|
+
this.#setState({
|
|
201
|
+
items: newItems,
|
|
202
|
+
itemTimestamps: newTimestamps,
|
|
203
|
+
expirationCount: this.store.state.expirationCount + 1
|
|
204
|
+
});
|
|
205
|
+
this.options.onExpire?.(expiredItem, this);
|
|
206
|
+
}
|
|
207
|
+
if (expiredIndices.length > 0) {
|
|
208
|
+
this.options.onItemsChange?.(this);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
this.peekNextItem = (position = "front") => {
|
|
212
|
+
if (position === "front") {
|
|
213
|
+
return this.store.state.items[0];
|
|
214
|
+
}
|
|
215
|
+
return this.store.state.items[this.store.state.size - 1];
|
|
216
|
+
};
|
|
217
|
+
this.peekAllItems = () => {
|
|
218
|
+
return [...this.store.state.items];
|
|
219
|
+
};
|
|
220
|
+
this.start = () => {
|
|
221
|
+
this.#setState({ isRunning: true });
|
|
222
|
+
if (!this.store.state.pendingTick && !this.store.state.isEmpty) {
|
|
223
|
+
this.#tick();
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
this.stop = () => {
|
|
227
|
+
this.#clearTimeout();
|
|
228
|
+
this.#setState({ isRunning: false, pendingTick: false });
|
|
229
|
+
};
|
|
230
|
+
this.#clearTimeout = () => {
|
|
231
|
+
if (this.#timeoutId) {
|
|
232
|
+
clearTimeout(this.#timeoutId);
|
|
233
|
+
this.#timeoutId = null;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
this.clear = () => {
|
|
237
|
+
this.#setState({ items: [], itemTimestamps: [] });
|
|
238
|
+
this.options.onItemsChange?.(this);
|
|
239
|
+
};
|
|
240
|
+
this.reset = () => {
|
|
241
|
+
this.#setState(getDefaultQueuerState());
|
|
242
|
+
this.options.onItemsChange?.(this);
|
|
243
|
+
};
|
|
244
|
+
this.options = {
|
|
245
|
+
...defaultOptions,
|
|
246
|
+
...initialOptions
|
|
247
|
+
};
|
|
248
|
+
const isInitiallyRunning = this.options.initialState?.isRunning ?? this.options.started ?? true;
|
|
249
|
+
this.#setState({
|
|
250
|
+
...this.options.initialState,
|
|
251
|
+
isRunning: isInitiallyRunning
|
|
252
|
+
});
|
|
253
|
+
if (this.options.initialState?.items) {
|
|
254
|
+
if (this.store.state.isRunning) {
|
|
255
|
+
this.#tick();
|
|
194
256
|
}
|
|
195
|
-
}
|
|
196
|
-
if (this._running && !this._pendingTick) {
|
|
197
|
-
this._pendingTick = true;
|
|
198
|
-
this.tick();
|
|
199
|
-
}
|
|
200
|
-
if (runOnUpdate) {
|
|
201
|
-
this._options.onItemsChange(this);
|
|
202
|
-
}
|
|
203
|
-
return true;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Removes and returns the next item from the queue without executing the function.
|
|
207
|
-
* Use for manual queue management. Normally, use execute() to process items.
|
|
208
|
-
*
|
|
209
|
-
* Example usage:
|
|
210
|
-
* ```ts
|
|
211
|
-
* // FIFO
|
|
212
|
-
* queuer.getNextItem();
|
|
213
|
-
* // LIFO
|
|
214
|
-
* queuer.getNextItem('back');
|
|
215
|
-
* ```
|
|
216
|
-
*/
|
|
217
|
-
getNextItem(position = this._options.getItemsFrom) {
|
|
218
|
-
let item;
|
|
219
|
-
if (position === "front") {
|
|
220
|
-
item = this._items.shift();
|
|
221
|
-
this._itemTimestamps.shift();
|
|
222
257
|
} else {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
return item;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Removes and returns the next item from the queue and processes it using the provided function.
|
|
233
|
-
*
|
|
234
|
-
* Example usage:
|
|
235
|
-
* ```ts
|
|
236
|
-
* queuer.execute();
|
|
237
|
-
* // LIFO
|
|
238
|
-
* queuer.execute('back');
|
|
239
|
-
* ```
|
|
240
|
-
*/
|
|
241
|
-
execute(position) {
|
|
242
|
-
const item = this.getNextItem(position);
|
|
243
|
-
if (item !== void 0) {
|
|
244
|
-
this.fn(item);
|
|
245
|
-
this._executionCount++;
|
|
246
|
-
this._options.onExecute(item, this);
|
|
247
|
-
}
|
|
248
|
-
return item;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Returns the next item in the queue without removing it.
|
|
252
|
-
*
|
|
253
|
-
* Example usage:
|
|
254
|
-
* ```ts
|
|
255
|
-
* queuer.peekNextItem(); // front
|
|
256
|
-
* queuer.peekNextItem('back'); // back
|
|
257
|
-
* ```
|
|
258
|
-
*/
|
|
259
|
-
peekNextItem(position = this._options.getItemsFrom) {
|
|
260
|
-
if (position === "front") {
|
|
261
|
-
return this._items[0];
|
|
258
|
+
for (let i = 0; i < (this.options.initialItems?.length ?? 0); i++) {
|
|
259
|
+
const item = this.options.initialItems[i];
|
|
260
|
+
const isLast = i === (this.options.initialItems?.length ?? 0) - 1;
|
|
261
|
+
this.addItem(item, this.options.addItemsTo ?? "back", isLast);
|
|
262
|
+
}
|
|
262
263
|
}
|
|
263
|
-
return this._items[this._items.length - 1];
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Returns true if the queue is empty (no pending items).
|
|
267
|
-
*/
|
|
268
|
-
getIsEmpty() {
|
|
269
|
-
return this._items.length === 0;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Returns true if the queue is full (reached maxSize).
|
|
273
|
-
*/
|
|
274
|
-
getIsFull() {
|
|
275
|
-
return this._items.length >= this._options.maxSize;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Returns the number of pending items in the queue.
|
|
279
|
-
*/
|
|
280
|
-
getSize() {
|
|
281
|
-
return this._items.length;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Returns a copy of all items in the queue.
|
|
285
|
-
*/
|
|
286
|
-
peekAllItems() {
|
|
287
|
-
return [...this._items];
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Returns the number of items that have been processed and removed from the queue.
|
|
291
|
-
*/
|
|
292
|
-
getExecutionCount() {
|
|
293
|
-
return this._executionCount;
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Returns the number of items that have been rejected from being added to the queue.
|
|
297
|
-
*/
|
|
298
|
-
getRejectionCount() {
|
|
299
|
-
return this._rejectionCount;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Returns the number of items that have expired and been removed from the queue.
|
|
303
|
-
*/
|
|
304
|
-
getExpirationCount() {
|
|
305
|
-
return this._expirationCount;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Returns true if the queuer is currently running (processing items).
|
|
309
|
-
*/
|
|
310
|
-
getIsRunning() {
|
|
311
|
-
return this._running;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Returns true if the queuer is running but has no items to process.
|
|
315
|
-
*/
|
|
316
|
-
getIsIdle() {
|
|
317
|
-
return this._running && this.getIsEmpty();
|
|
318
264
|
}
|
|
265
|
+
#timeoutId;
|
|
266
|
+
#setState;
|
|
267
|
+
#getWait;
|
|
268
|
+
#tick;
|
|
269
|
+
#checkExpiredItems;
|
|
270
|
+
#clearTimeout;
|
|
319
271
|
}
|
|
320
|
-
function queue(fn,
|
|
321
|
-
const queuer = new Queuer(fn,
|
|
322
|
-
return queuer.addItem
|
|
272
|
+
function queue(fn, initialOptions) {
|
|
273
|
+
const queuer = new Queuer(fn, initialOptions);
|
|
274
|
+
return queuer.addItem;
|
|
323
275
|
}
|
|
324
276
|
exports.Queuer = Queuer;
|
|
325
277
|
exports.queue = queue;
|