@oscarpalmer/atoms 0.151.0 → 0.152.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/atoms.full.js +50 -55
- package/dist/function/index.js +24 -0
- package/dist/index.js +1 -2
- package/dist/internal/function/timer.js +31 -0
- package/dist/promise/delay.js +6 -9
- package/dist/promise/timed.js +7 -10
- package/package.json +2 -18
- package/src/function/index.ts +41 -0
- package/src/index.ts +1 -3
- package/src/internal/function/timer.ts +68 -0
- package/src/promise/delay.ts +9 -12
- package/src/promise/timed.ts +11 -14
- package/types/function/{debounce.d.ts → index.d.ts} +9 -0
- package/types/index.d.ts +1 -3
- package/types/internal/function/timer.d.ts +7 -0
- package/dist/function/debounce.js +0 -13
- package/dist/function/misc.js +0 -2
- package/dist/function/throttle.js +0 -11
- package/dist/internal/function/limiter.js +0 -28
- package/src/function/debounce.ts +0 -21
- package/src/function/misc.ts +0 -1
- package/src/function/throttle.ts +0 -19
- package/src/internal/function/limiter.ts +0 -51
- package/types/function/misc.d.ts +0 -1
- package/types/function/throttle.d.ts +0 -8
- package/types/internal/function/limiter.d.ts +0 -3
package/dist/atoms.full.js
CHANGED
|
@@ -677,44 +677,40 @@ function unique(array, key) {
|
|
|
677
677
|
if (!Array.isArray(array)) return [];
|
|
678
678
|
return array.length > 1 ? findValues("unique", array, [key, void 0]).matched : array;
|
|
679
679
|
}
|
|
680
|
-
function
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
680
|
+
function getInterval(value) {
|
|
681
|
+
return typeof value === "number" && value > 0 ? value : 0;
|
|
682
|
+
}
|
|
683
|
+
function getTimer(type, callback, time) {
|
|
684
|
+
const interval = getInterval(time);
|
|
685
|
+
function run(now) {
|
|
686
|
+
start ??= now;
|
|
687
|
+
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
688
|
+
if (throttle) start = now;
|
|
689
|
+
callback(...args);
|
|
690
|
+
} else frame = requestAnimationFrame(run);
|
|
689
691
|
}
|
|
692
|
+
const throttle = type === TIMER_THROTTLE;
|
|
693
|
+
let args;
|
|
690
694
|
let frame;
|
|
691
|
-
let
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
step(now, parameters);
|
|
697
|
-
});
|
|
695
|
+
let start;
|
|
696
|
+
const timer = (...parameters) => {
|
|
697
|
+
timer.cancel();
|
|
698
|
+
args = parameters;
|
|
699
|
+
frame = requestAnimationFrame(run);
|
|
698
700
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
cancelAnimationFrame(frame);
|
|
702
|
-
frame = void 0;
|
|
703
|
-
}
|
|
701
|
+
timer.cancel = () => {
|
|
702
|
+
cancelAnimationFrame(frame);
|
|
704
703
|
};
|
|
705
|
-
return
|
|
704
|
+
return timer;
|
|
706
705
|
}
|
|
706
|
+
const OFFSET = 5;
|
|
707
|
+
const TIMER_DEBOUNCE = "debounce";
|
|
708
|
+
const TIMER_THROTTLE = "throttle";
|
|
709
|
+
const TIMER_WAIT = "wait";
|
|
707
710
|
/**
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
711
|
-
* @param callback Callback to debounce
|
|
712
|
-
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
713
|
-
* @returns Debounced callback with a `cancel` method
|
|
711
|
+
* A function that does nothing, which can be useful, I guess…
|
|
714
712
|
*/
|
|
715
|
-
function
|
|
716
|
-
return getLimiter(callback, false, time);
|
|
717
|
-
}
|
|
713
|
+
function noop() {}
|
|
718
714
|
/**
|
|
719
715
|
* Is the number between a minimum and maximum value?
|
|
720
716
|
* @param value Value to check
|
|
@@ -922,13 +918,24 @@ function memoize(callback, options) {
|
|
|
922
918
|
}
|
|
923
919
|
const DEFAULT_CACHE_SIZE = 1024;
|
|
924
920
|
/**
|
|
921
|
+
* Debounce a function, ensuring it is only called after `time` milliseconds have passed
|
|
922
|
+
*
|
|
923
|
+
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
924
|
+
* @param callback Callback to debounce
|
|
925
|
+
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
926
|
+
* @returns Debounced callback with a `cancel` method
|
|
927
|
+
*/
|
|
928
|
+
function debounce(callback, time) {
|
|
929
|
+
return getTimer(TIMER_DEBOUNCE, callback, time);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
925
932
|
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
926
933
|
* @param callback Callback to throttle
|
|
927
934
|
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
928
935
|
* @returns Throttled callback with a `cancel` method
|
|
929
936
|
*/
|
|
930
937
|
function throttle(callback, time) {
|
|
931
|
-
return
|
|
938
|
+
return getTimer(TIMER_THROTTLE, callback, time);
|
|
932
939
|
}
|
|
933
940
|
function _isResult(value, okValue) {
|
|
934
941
|
if (!isPlainObject(value)) return false;
|
|
@@ -1029,10 +1036,6 @@ const MESSAGE_PIPE_ARRAY = "Pipe expected to receive an array of functions";
|
|
|
1029
1036
|
const MESSAGE_PIPE_PROMISE = "Synchronous Pipe received a promise. Use `pipe.async` instead.";
|
|
1030
1037
|
const assertFlowFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_FLOW_ARRAY, TypeError);
|
|
1031
1038
|
const assertPipeFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_PIPE_ARRAY, TypeError);
|
|
1032
|
-
/**
|
|
1033
|
-
* A function that does nothing, which can be useful, I guess…
|
|
1034
|
-
*/
|
|
1035
|
-
function noop() {}
|
|
1036
1039
|
function equal(first, second, options) {
|
|
1037
1040
|
return equalValue(first, second, getEqualOptions(options));
|
|
1038
1041
|
}
|
|
@@ -3123,23 +3126,19 @@ async function toResult(value) {
|
|
|
3123
3126
|
}
|
|
3124
3127
|
async function getTimedPromise(promise, time, signal) {
|
|
3125
3128
|
function abort() {
|
|
3126
|
-
|
|
3129
|
+
timer.cancel();
|
|
3127
3130
|
rejector(signal.reason);
|
|
3128
3131
|
}
|
|
3129
|
-
function run(now) {
|
|
3130
|
-
start ??= now;
|
|
3131
|
-
if (time === 0 || now - start >= time - 5) settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
|
|
3132
|
-
else frame = requestAnimationFrame(run);
|
|
3133
|
-
}
|
|
3134
3132
|
signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
|
|
3135
|
-
|
|
3133
|
+
const timer = getTimer(TIMER_WAIT, () => {
|
|
3134
|
+
settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
|
|
3135
|
+
}, time);
|
|
3136
3136
|
let rejector;
|
|
3137
|
-
let start;
|
|
3138
3137
|
return Promise.race([promise, new Promise((_, reject) => {
|
|
3139
3138
|
rejector = reject;
|
|
3140
|
-
|
|
3139
|
+
timer();
|
|
3141
3140
|
})]).then((value) => {
|
|
3142
|
-
|
|
3141
|
+
timer.cancel();
|
|
3143
3142
|
signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
|
|
3144
3143
|
return value;
|
|
3145
3144
|
});
|
|
@@ -3154,24 +3153,20 @@ function delay(options) {
|
|
|
3154
3153
|
const { signal, time } = getPromiseOptions(options);
|
|
3155
3154
|
if (signal?.aborted ?? false) return Promise.reject(signal.reason);
|
|
3156
3155
|
function abort() {
|
|
3157
|
-
|
|
3156
|
+
timer.cancel();
|
|
3158
3157
|
rejector(signal.reason);
|
|
3159
3158
|
}
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
else frame = requestAnimationFrame(run);
|
|
3164
|
-
}
|
|
3159
|
+
const timer = getTimer(TIMER_WAIT, () => {
|
|
3160
|
+
settlePromise(abort, resolver, void 0, signal);
|
|
3161
|
+
}, time);
|
|
3165
3162
|
signal?.addEventListener("abort", abort, PROMISE_ABORT_OPTIONS);
|
|
3166
|
-
let frame;
|
|
3167
3163
|
let rejector;
|
|
3168
3164
|
let resolver;
|
|
3169
|
-
let start;
|
|
3170
3165
|
return new Promise((resolve, reject) => {
|
|
3171
3166
|
rejector = reject;
|
|
3172
3167
|
resolver = resolve;
|
|
3173
3168
|
if (time === 0) settlePromise(abort, resolve, void 0, signal);
|
|
3174
|
-
else
|
|
3169
|
+
else timer();
|
|
3175
3170
|
});
|
|
3176
3171
|
}
|
|
3177
3172
|
async function attemptPromise(value, options) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { noop } from "../internal/function/misc.js";
|
|
2
|
+
import { TIMER_DEBOUNCE, TIMER_THROTTLE, getTimer } from "../internal/function/timer.js";
|
|
3
|
+
import { memoize } from "./memoize.js";
|
|
4
|
+
/**
|
|
5
|
+
* Debounce a function, ensuring it is only called after `time` milliseconds have passed
|
|
6
|
+
*
|
|
7
|
+
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
8
|
+
* @param callback Callback to debounce
|
|
9
|
+
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
10
|
+
* @returns Debounced callback with a `cancel` method
|
|
11
|
+
*/
|
|
12
|
+
function debounce(callback, time) {
|
|
13
|
+
return getTimer(TIMER_DEBOUNCE, callback, time);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
17
|
+
* @param callback Callback to throttle
|
|
18
|
+
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
19
|
+
* @returns Throttled callback with a `cancel` method
|
|
20
|
+
*/
|
|
21
|
+
function throttle(callback, time) {
|
|
22
|
+
return getTimer(TIMER_THROTTLE, callback, time);
|
|
23
|
+
}
|
|
24
|
+
export { debounce, memoize, noop, throttle };
|
package/dist/index.js
CHANGED
|
@@ -36,10 +36,9 @@ import { rgbToHex, rgbToHsl, rgbToHsla } from "./color/space/rgb.js";
|
|
|
36
36
|
import { getNormalizedHex, hexToHsl, hexToHsla, hexToRgb, hexToRgba } from "./color/space/hex.js";
|
|
37
37
|
import { hslToHex, hslToRgb, hslToRgba } from "./color/space/hsl.js";
|
|
38
38
|
import { getColor } from "./color/index.js";
|
|
39
|
-
import { debounce } from "./function/debounce.js";
|
|
40
39
|
import { SizedMap } from "./sized/map.js";
|
|
41
40
|
import { memoize } from "./function/memoize.js";
|
|
42
|
-
import { throttle } from "./function/
|
|
41
|
+
import { debounce, throttle } from "./function/index.js";
|
|
43
42
|
import { isError, isOk, isResult } from "./internal/result.js";
|
|
44
43
|
import { flow, pipe } from "./function/work.js";
|
|
45
44
|
import { equal } from "./internal/value/equal.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function getInterval(value) {
|
|
2
|
+
return typeof value === "number" && value > 0 ? value : 0;
|
|
3
|
+
}
|
|
4
|
+
function getTimer(type, callback, time) {
|
|
5
|
+
const interval = getInterval(time);
|
|
6
|
+
function run(now) {
|
|
7
|
+
start ??= now;
|
|
8
|
+
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
9
|
+
if (throttle) start = now;
|
|
10
|
+
callback(...args);
|
|
11
|
+
} else frame = requestAnimationFrame(run);
|
|
12
|
+
}
|
|
13
|
+
const throttle = type === TIMER_THROTTLE;
|
|
14
|
+
let args;
|
|
15
|
+
let frame;
|
|
16
|
+
let start;
|
|
17
|
+
const timer = (...parameters) => {
|
|
18
|
+
timer.cancel();
|
|
19
|
+
args = parameters;
|
|
20
|
+
frame = requestAnimationFrame(run);
|
|
21
|
+
};
|
|
22
|
+
timer.cancel = () => {
|
|
23
|
+
cancelAnimationFrame(frame);
|
|
24
|
+
};
|
|
25
|
+
return timer;
|
|
26
|
+
}
|
|
27
|
+
var OFFSET = 5;
|
|
28
|
+
const TIMER_DEBOUNCE = "debounce";
|
|
29
|
+
const TIMER_THROTTLE = "throttle";
|
|
30
|
+
const TIMER_WAIT = "wait";
|
|
31
|
+
export { TIMER_DEBOUNCE, TIMER_THROTTLE, TIMER_WAIT, getTimer };
|
package/dist/promise/delay.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TIMER_WAIT, getTimer } from "../internal/function/timer.js";
|
|
1
2
|
import { PROMISE_ABORT_OPTIONS } from "./models.js";
|
|
2
3
|
import { getPromiseOptions } from "./helpers.js";
|
|
3
4
|
import { settlePromise } from "./misc.js";
|
|
@@ -5,24 +6,20 @@ function delay(options) {
|
|
|
5
6
|
const { signal, time } = getPromiseOptions(options);
|
|
6
7
|
if (signal?.aborted ?? false) return Promise.reject(signal.reason);
|
|
7
8
|
function abort() {
|
|
8
|
-
|
|
9
|
+
timer.cancel();
|
|
9
10
|
rejector(signal.reason);
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
else frame = requestAnimationFrame(run);
|
|
15
|
-
}
|
|
12
|
+
const timer = getTimer(TIMER_WAIT, () => {
|
|
13
|
+
settlePromise(abort, resolver, void 0, signal);
|
|
14
|
+
}, time);
|
|
16
15
|
signal?.addEventListener("abort", abort, PROMISE_ABORT_OPTIONS);
|
|
17
|
-
let frame;
|
|
18
16
|
let rejector;
|
|
19
17
|
let resolver;
|
|
20
|
-
let start;
|
|
21
18
|
return new Promise((resolve, reject) => {
|
|
22
19
|
rejector = reject;
|
|
23
20
|
resolver = resolve;
|
|
24
21
|
if (time === 0) settlePromise(abort, resolve, void 0, signal);
|
|
25
|
-
else
|
|
22
|
+
else timer();
|
|
26
23
|
});
|
|
27
24
|
}
|
|
28
25
|
export { delay };
|
package/dist/promise/timed.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
|
+
import { TIMER_WAIT, getTimer } from "../internal/function/timer.js";
|
|
1
2
|
import { PROMISE_ABORT_OPTIONS, PROMISE_EVENT_NAME, PROMISE_MESSAGE_EXPECTATION_TIMED, PromiseTimeoutError } from "./models.js";
|
|
2
3
|
import { getPromiseOptions } from "./helpers.js";
|
|
3
4
|
import { settlePromise } from "./misc.js";
|
|
4
5
|
async function getTimedPromise(promise, time, signal) {
|
|
5
6
|
function abort() {
|
|
6
|
-
|
|
7
|
+
timer.cancel();
|
|
7
8
|
rejector(signal.reason);
|
|
8
9
|
}
|
|
9
|
-
function run(now) {
|
|
10
|
-
start ??= now;
|
|
11
|
-
if (time === 0 || now - start >= time - 5) settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
|
|
12
|
-
else frame = requestAnimationFrame(run);
|
|
13
|
-
}
|
|
14
10
|
signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
|
|
15
|
-
|
|
11
|
+
const timer = getTimer(TIMER_WAIT, () => {
|
|
12
|
+
settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
|
|
13
|
+
}, time);
|
|
16
14
|
let rejector;
|
|
17
|
-
let start;
|
|
18
15
|
return Promise.race([promise, new Promise((_, reject) => {
|
|
19
16
|
rejector = reject;
|
|
20
|
-
|
|
17
|
+
timer();
|
|
21
18
|
})]).then((value) => {
|
|
22
|
-
|
|
19
|
+
timer.cancel();
|
|
23
20
|
signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
|
|
24
21
|
return value;
|
|
25
22
|
});
|
package/package.json
CHANGED
|
@@ -50,26 +50,10 @@
|
|
|
50
50
|
"types": "./types/color/index.d.ts",
|
|
51
51
|
"default": "./dist/color/index.js"
|
|
52
52
|
},
|
|
53
|
-
"./
|
|
54
|
-
"types": "./types/internal/frame-rate.d.ts",
|
|
55
|
-
"default": "./dist/internal/frame-rate.js"
|
|
56
|
-
},
|
|
57
|
-
"./function/debounce": {
|
|
58
|
-
"types": "./types/function/debounce.d.ts",
|
|
59
|
-
"default": "./dist/function/debounce.js"
|
|
60
|
-
},
|
|
61
|
-
"./function/memoize": {
|
|
53
|
+
"./function": {
|
|
62
54
|
"types": "./types/function/memoize.d.ts",
|
|
63
55
|
"default": "./dist/function/memoize.js"
|
|
64
56
|
},
|
|
65
|
-
"./function/misc": {
|
|
66
|
-
"types": "./types/function/misc.d.ts",
|
|
67
|
-
"default": "./dist/function/misc.js"
|
|
68
|
-
},
|
|
69
|
-
"./function/throttle": {
|
|
70
|
-
"types": "./types/function/throttle.d.ts",
|
|
71
|
-
"default": "./dist/function/throttle.js"
|
|
72
|
-
},
|
|
73
57
|
"./function/work": {
|
|
74
58
|
"types": "./types/function/work.d.ts",
|
|
75
59
|
"default": "./dist/function/work.js"
|
|
@@ -192,5 +176,5 @@
|
|
|
192
176
|
},
|
|
193
177
|
"type": "module",
|
|
194
178
|
"types": "./types/index.d.ts",
|
|
195
|
-
"version": "0.
|
|
179
|
+
"version": "0.152.0"
|
|
196
180
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {getTimer, TIMER_DEBOUNCE, TIMER_THROTTLE} from '../internal/function/timer';
|
|
2
|
+
import type {CancelableCallback, GenericCallback} from '../models';
|
|
3
|
+
|
|
4
|
+
// #region Functions
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Debounce a function, ensuring it is only called after `time` milliseconds have passed
|
|
8
|
+
*
|
|
9
|
+
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
10
|
+
* @param callback Callback to debounce
|
|
11
|
+
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
12
|
+
* @returns Debounced callback with a `cancel` method
|
|
13
|
+
*/
|
|
14
|
+
export function debounce<Callback extends GenericCallback>(
|
|
15
|
+
callback: Callback,
|
|
16
|
+
time?: number,
|
|
17
|
+
): CancelableCallback<Callback> {
|
|
18
|
+
return getTimer(TIMER_DEBOUNCE, callback, time);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
23
|
+
* @param callback Callback to throttle
|
|
24
|
+
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
25
|
+
* @returns Throttled callback with a `cancel` method
|
|
26
|
+
*/
|
|
27
|
+
export function throttle<Callback extends GenericCallback>(
|
|
28
|
+
callback: Callback,
|
|
29
|
+
time?: number,
|
|
30
|
+
): CancelableCallback<Callback> {
|
|
31
|
+
return getTimer(TIMER_THROTTLE, callback, time);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// #endregion
|
|
35
|
+
|
|
36
|
+
// #region Exports
|
|
37
|
+
|
|
38
|
+
export {noop} from '../internal/function/misc';
|
|
39
|
+
export {memoize, type Memoized, type MemoizedOptions} from './memoize';
|
|
40
|
+
|
|
41
|
+
// #endregion
|
package/src/index.ts
CHANGED
|
@@ -4,9 +4,7 @@ export * from './array/to-map';
|
|
|
4
4
|
export * from './array/to-record';
|
|
5
5
|
export * from './array/unique';
|
|
6
6
|
|
|
7
|
-
export * from './function/
|
|
8
|
-
export * from './function/memoize';
|
|
9
|
-
export * from './function/throttle';
|
|
7
|
+
export * from './function/index';
|
|
10
8
|
export * from './function/work';
|
|
11
9
|
|
|
12
10
|
export * from './internal/function/misc';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type {CancelableCallback, GenericCallback} from '../../models';
|
|
2
|
+
|
|
3
|
+
// #region Types
|
|
4
|
+
|
|
5
|
+
type TimerType = 'debounce' | 'throttle' | 'wait';
|
|
6
|
+
|
|
7
|
+
// #endregion
|
|
8
|
+
|
|
9
|
+
// #region Functions
|
|
10
|
+
|
|
11
|
+
function getInterval(value: unknown): number {
|
|
12
|
+
return typeof value === 'number' && value > 0 ? value : 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getTimer<Callback extends GenericCallback>(
|
|
16
|
+
type: TimerType,
|
|
17
|
+
callback: Callback,
|
|
18
|
+
time?: number,
|
|
19
|
+
): CancelableCallback<Callback> {
|
|
20
|
+
const interval = getInterval(time);
|
|
21
|
+
|
|
22
|
+
function run(now: DOMHighResTimeStamp): void {
|
|
23
|
+
start ??= now;
|
|
24
|
+
|
|
25
|
+
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
26
|
+
if (throttle) {
|
|
27
|
+
start = now;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
callback(...args);
|
|
31
|
+
} else {
|
|
32
|
+
frame = requestAnimationFrame(run);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const throttle = type === TIMER_THROTTLE;
|
|
37
|
+
|
|
38
|
+
let args: Parameters<Callback>;
|
|
39
|
+
let frame: DOMHighResTimeStamp | undefined;
|
|
40
|
+
let start: DOMHighResTimeStamp;
|
|
41
|
+
|
|
42
|
+
const timer = (...parameters: Parameters<Callback>): void => {
|
|
43
|
+
timer.cancel();
|
|
44
|
+
|
|
45
|
+
args = parameters;
|
|
46
|
+
frame = requestAnimationFrame(run);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
timer.cancel = (): void => {
|
|
50
|
+
cancelAnimationFrame(frame!);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return timer as CancelableCallback<Callback>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// #endregion
|
|
57
|
+
|
|
58
|
+
// #region Variables
|
|
59
|
+
|
|
60
|
+
const OFFSET = 5;
|
|
61
|
+
|
|
62
|
+
export const TIMER_DEBOUNCE: TimerType = 'debounce';
|
|
63
|
+
|
|
64
|
+
export const TIMER_THROTTLE: TimerType = 'throttle';
|
|
65
|
+
|
|
66
|
+
export const TIMER_WAIT: TimerType = 'wait';
|
|
67
|
+
|
|
68
|
+
// #endregion
|
package/src/promise/delay.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {getTimer, TIMER_WAIT} from '../internal/function/timer';
|
|
1
2
|
import {getPromiseOptions} from './helpers';
|
|
2
3
|
import {settlePromise} from './misc';
|
|
3
4
|
import {PROMISE_ABORT_OPTIONS, type PromiseOptions} from './models';
|
|
@@ -26,27 +27,23 @@ export function delay(options?: unknown): Promise<void> {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
function abort(): void {
|
|
29
|
-
|
|
30
|
+
timer.cancel();
|
|
30
31
|
|
|
31
32
|
rejector(signal!.reason);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (now - start >= time - 5) {
|
|
35
|
+
const timer = getTimer(
|
|
36
|
+
TIMER_WAIT,
|
|
37
|
+
() => {
|
|
38
38
|
settlePromise(abort, resolver, undefined, signal);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
39
|
+
},
|
|
40
|
+
time,
|
|
41
|
+
);
|
|
43
42
|
|
|
44
43
|
signal?.addEventListener('abort', abort, PROMISE_ABORT_OPTIONS);
|
|
45
44
|
|
|
46
|
-
let frame: DOMHighResTimeStamp;
|
|
47
45
|
let rejector: (reason: unknown) => void;
|
|
48
46
|
let resolver: () => void;
|
|
49
|
-
let start: DOMHighResTimeStamp;
|
|
50
47
|
|
|
51
48
|
return new Promise((resolve, reject) => {
|
|
52
49
|
rejector = reject;
|
|
@@ -55,7 +52,7 @@ export function delay(options?: unknown): Promise<void> {
|
|
|
55
52
|
if (time === 0) {
|
|
56
53
|
settlePromise(abort, resolve, undefined, signal);
|
|
57
54
|
} else {
|
|
58
|
-
|
|
55
|
+
timer();
|
|
59
56
|
}
|
|
60
57
|
});
|
|
61
58
|
}
|
package/src/promise/timed.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {getTimer, TIMER_WAIT} from '../internal/function/timer';
|
|
1
2
|
import type {RequiredKeys} from '../models';
|
|
2
3
|
import {getPromiseOptions} from './helpers';
|
|
3
4
|
import {settlePromise} from './misc';
|
|
@@ -17,36 +18,32 @@ export async function getTimedPromise<Value>(
|
|
|
17
18
|
signal?: AbortSignal,
|
|
18
19
|
): Promise<Value> {
|
|
19
20
|
function abort(): void {
|
|
20
|
-
|
|
21
|
+
timer.cancel();
|
|
21
22
|
|
|
22
23
|
rejector(signal!.reason);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
start ??= now;
|
|
26
|
+
signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
const timer = getTimer(
|
|
29
|
+
TIMER_WAIT,
|
|
30
|
+
() => {
|
|
29
31
|
settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
|
|
32
|
+
},
|
|
33
|
+
time,
|
|
34
|
+
);
|
|
36
35
|
|
|
37
|
-
let frame: DOMHighResTimeStamp;
|
|
38
36
|
let rejector: (reason: unknown) => void;
|
|
39
|
-
let start: DOMHighResTimeStamp;
|
|
40
37
|
|
|
41
38
|
return Promise.race<Value>([
|
|
42
39
|
promise,
|
|
43
40
|
new Promise((_, reject) => {
|
|
44
41
|
rejector = reject;
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
timer();
|
|
47
44
|
}),
|
|
48
45
|
]).then(value => {
|
|
49
|
-
|
|
46
|
+
timer.cancel();
|
|
50
47
|
|
|
51
48
|
signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
|
|
52
49
|
|
|
@@ -8,3 +8,12 @@ import type { CancelableCallback, GenericCallback } from '../models';
|
|
|
8
8
|
* @returns Debounced callback with a `cancel` method
|
|
9
9
|
*/
|
|
10
10
|
export declare function debounce<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
|
|
11
|
+
/**
|
|
12
|
+
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
13
|
+
* @param callback Callback to throttle
|
|
14
|
+
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
15
|
+
* @returns Throttled callback with a `cancel` method
|
|
16
|
+
*/
|
|
17
|
+
export declare function throttle<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
|
|
18
|
+
export { noop } from '../internal/function/misc';
|
|
19
|
+
export { memoize, type Memoized, type MemoizedOptions } from './memoize';
|
package/types/index.d.ts
CHANGED
|
@@ -3,9 +3,7 @@ export * from './array/misc';
|
|
|
3
3
|
export * from './array/to-map';
|
|
4
4
|
export * from './array/to-record';
|
|
5
5
|
export * from './array/unique';
|
|
6
|
-
export * from './function/
|
|
7
|
-
export * from './function/memoize';
|
|
8
|
-
export * from './function/throttle';
|
|
6
|
+
export * from './function/index';
|
|
9
7
|
export * from './function/work';
|
|
10
8
|
export * from './internal/function/misc';
|
|
11
9
|
export * from './internal/string';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CancelableCallback, GenericCallback } from '../../models';
|
|
2
|
+
type TimerType = 'debounce' | 'throttle' | 'wait';
|
|
3
|
+
export declare function getTimer<Callback extends GenericCallback>(type: TimerType, callback: Callback, time?: number): CancelableCallback<Callback>;
|
|
4
|
+
export declare const TIMER_DEBOUNCE: TimerType;
|
|
5
|
+
export declare const TIMER_THROTTLE: TimerType;
|
|
6
|
+
export declare const TIMER_WAIT: TimerType;
|
|
7
|
+
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { getLimiter } from "../internal/function/limiter.js";
|
|
2
|
-
/**
|
|
3
|
-
* Debounce a function, ensuring it is only called after `time` milliseconds have passed
|
|
4
|
-
*
|
|
5
|
-
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
6
|
-
* @param callback Callback to debounce
|
|
7
|
-
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
8
|
-
* @returns Debounced callback with a `cancel` method
|
|
9
|
-
*/
|
|
10
|
-
function debounce(callback, time) {
|
|
11
|
-
return getLimiter(callback, false, time);
|
|
12
|
-
}
|
|
13
|
-
export { debounce };
|
package/dist/function/misc.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { getLimiter } from "../internal/function/limiter.js";
|
|
2
|
-
/**
|
|
3
|
-
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
4
|
-
* @param callback Callback to throttle
|
|
5
|
-
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
6
|
-
* @returns Throttled callback with a `cancel` method
|
|
7
|
-
*/
|
|
8
|
-
function throttle(callback, time) {
|
|
9
|
-
return getLimiter(callback, true, time);
|
|
10
|
-
}
|
|
11
|
-
export { throttle };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
function getLimiter(callback, throttler, time) {
|
|
2
|
-
const interval = typeof time === "number" && time > 0 ? time : 0;
|
|
3
|
-
function step(now, parameters) {
|
|
4
|
-
if (interval === 0 || now - timestamp >= interval) {
|
|
5
|
-
if (throttler) timestamp = now;
|
|
6
|
-
callback(...parameters);
|
|
7
|
-
} else frame = requestAnimationFrame((next) => {
|
|
8
|
-
step(next, parameters);
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
let frame;
|
|
12
|
-
let timestamp;
|
|
13
|
-
const limiter = (...parameters) => {
|
|
14
|
-
limiter.cancel();
|
|
15
|
-
frame = requestAnimationFrame((now) => {
|
|
16
|
-
timestamp ??= now;
|
|
17
|
-
step(now, parameters);
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
limiter.cancel = () => {
|
|
21
|
-
if (frame != null) {
|
|
22
|
-
cancelAnimationFrame(frame);
|
|
23
|
-
frame = void 0;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
return limiter;
|
|
27
|
-
}
|
|
28
|
-
export { getLimiter };
|
package/src/function/debounce.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {getLimiter} from '../internal/function/limiter';
|
|
2
|
-
import type {CancelableCallback, GenericCallback} from '../models';
|
|
3
|
-
|
|
4
|
-
// #region Functions
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Debounce a function, ensuring it is only called after `time` milliseconds have passed
|
|
8
|
-
*
|
|
9
|
-
* On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
|
|
10
|
-
* @param callback Callback to debounce
|
|
11
|
-
* @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
|
|
12
|
-
* @returns Debounced callback with a `cancel` method
|
|
13
|
-
*/
|
|
14
|
-
export function debounce<Callback extends GenericCallback>(
|
|
15
|
-
callback: Callback,
|
|
16
|
-
time?: number,
|
|
17
|
-
): CancelableCallback<Callback> {
|
|
18
|
-
return getLimiter(callback, false, time);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// #endregion
|
package/src/function/misc.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {noop} from '../internal/function/misc';
|
package/src/function/throttle.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {getLimiter} from '../internal/function/limiter';
|
|
2
|
-
import type {CancelableCallback, GenericCallback} from '../models';
|
|
3
|
-
|
|
4
|
-
// #region Functions
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
8
|
-
* @param callback Callback to throttle
|
|
9
|
-
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
10
|
-
* @returns Throttled callback with a `cancel` method
|
|
11
|
-
*/
|
|
12
|
-
export function throttle<Callback extends GenericCallback>(
|
|
13
|
-
callback: Callback,
|
|
14
|
-
time?: number,
|
|
15
|
-
): CancelableCallback<Callback> {
|
|
16
|
-
return getLimiter(callback, true, time);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// #endregion
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type {CancelableCallback} from '../../models';
|
|
2
|
-
import type {GenericCallback} from '../../models';
|
|
3
|
-
|
|
4
|
-
// #region Functions
|
|
5
|
-
|
|
6
|
-
export function getLimiter<Callback extends GenericCallback>(
|
|
7
|
-
callback: Callback,
|
|
8
|
-
throttler: boolean,
|
|
9
|
-
time?: number,
|
|
10
|
-
): CancelableCallback<Callback> {
|
|
11
|
-
const interval = typeof time === 'number' && time > 0 ? time : 0;;
|
|
12
|
-
|
|
13
|
-
function step(now: DOMHighResTimeStamp, parameters: Parameters<Callback>): void {
|
|
14
|
-
if (interval === 0 || now - timestamp >= interval) {
|
|
15
|
-
if (throttler) {
|
|
16
|
-
timestamp = now;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
callback(...parameters);
|
|
20
|
-
} else {
|
|
21
|
-
frame = requestAnimationFrame(next => {
|
|
22
|
-
step(next, parameters);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
let frame: DOMHighResTimeStamp | undefined;
|
|
28
|
-
let timestamp: DOMHighResTimeStamp;
|
|
29
|
-
|
|
30
|
-
const limiter = (...parameters: Parameters<Callback>): void => {
|
|
31
|
-
limiter.cancel();
|
|
32
|
-
|
|
33
|
-
frame = requestAnimationFrame(now => {
|
|
34
|
-
timestamp ??= now;
|
|
35
|
-
|
|
36
|
-
step(now, parameters);
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
limiter.cancel = (): void => {
|
|
41
|
-
if (frame != null) {
|
|
42
|
-
cancelAnimationFrame(frame);
|
|
43
|
-
|
|
44
|
-
frame = undefined;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return limiter as CancelableCallback<Callback>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// #endregion
|
package/types/function/misc.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { noop } from '../internal/function/misc';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { CancelableCallback, GenericCallback } from '../models';
|
|
2
|
-
/**
|
|
3
|
-
* Throttle a function, ensuring it is only called once every `time` milliseconds
|
|
4
|
-
* @param callback Callback to throttle
|
|
5
|
-
* @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
|
|
6
|
-
* @returns Throttled callback with a `cancel` method
|
|
7
|
-
*/
|
|
8
|
-
export declare function throttle<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
|