@nemigo/helpers 0.13.3 → 1.5.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/aggregator.d.ts +33 -0
- package/dist/aggregator.js +44 -0
- package/dist/array.d.ts +33 -0
- package/dist/array.js +24 -0
- package/dist/async/context.d.ts +73 -0
- package/dist/async/context.js +90 -0
- package/dist/async/future.d.ts +54 -0
- package/dist/async/future.js +71 -0
- package/dist/async/index.d.ts +56 -27
- package/dist/async/index.js +63 -58
- package/dist/async/loader.d.ts +67 -0
- package/dist/async/loader.js +101 -0
- package/dist/async/queue.d.ts +51 -0
- package/dist/async/queue.js +84 -0
- package/dist/cases.d.ts +31 -21
- package/dist/cases.js +41 -37
- package/dist/clean.d.ts +44 -26
- package/dist/clean.js +67 -42
- package/dist/color/types.d.ts +31 -0
- package/dist/color/types.js +1 -0
- package/dist/datetime/delta.d.ts +28 -0
- package/dist/datetime/delta.js +65 -0
- package/dist/datetime/format.d.ts +53 -0
- package/dist/datetime/format.js +119 -0
- package/dist/datetime/index.d.ts +6 -0
- package/dist/datetime/index.js +22 -0
- package/dist/datetime/plural.d.ts +77 -0
- package/dist/datetime/plural.js +78 -0
- package/dist/emitter.d.ts +29 -17
- package/dist/emitter.js +35 -21
- package/dist/explorer.d.ts +22 -29
- package/dist/explorer.js +18 -16
- package/dist/files.d.ts +31 -2
- package/dist/files.js +33 -8
- package/dist/fish.d.ts +29 -0
- package/dist/fish.js +70 -0
- package/dist/html/cookie.d.ts +48 -0
- package/dist/html/cookie.js +37 -0
- package/dist/html/events.d.ts +133 -0
- package/dist/html/events.js +139 -0
- package/dist/html/index.d.ts +31 -0
- package/dist/html/index.js +61 -0
- package/dist/index.d.ts +38 -40
- package/dist/index.js +43 -56
- package/dist/jiff/apply.d.ts +93 -0
- package/dist/jiff/apply.js +64 -0
- package/dist/jiff/extract.d.ts +7 -0
- package/dist/jiff/extract.js +82 -0
- package/dist/jiff/types.d.ts +57 -0
- package/dist/jiff/types.js +1 -0
- package/dist/lens.d.ts +20 -31
- package/dist/lens.js +22 -37
- package/dist/msgpack.d.ts +11 -26
- package/dist/msgpack.js +9 -21
- package/dist/mutate.d.ts +70 -0
- package/dist/mutate.js +130 -0
- package/dist/omitter.d.ts +54 -34
- package/dist/omitter.js +33 -25
- package/dist/path.d.ts +20 -1
- package/dist/path.js +21 -2
- package/dist/phymath/format.d.ts +60 -0
- package/dist/phymath/format.js +34 -0
- package/dist/phymath/index.d.ts +30 -30
- package/dist/phymath/index.js +41 -33
- package/dist/promoter.d.ts +20 -12
- package/dist/promoter.js +24 -17
- package/dist/random.d.ts +20 -21
- package/dist/random.js +22 -23
- package/dist/rubles.d.ts +24 -0
- package/dist/rubles.js +24 -0
- package/dist/script.d.ts +60 -13
- package/dist/script.js +46 -10
- package/dist/string.d.ts +46 -92
- package/dist/string.js +46 -171
- package/dist/types.d.ts +144 -25
- package/dist/url/index.d.ts +12 -0
- package/dist/url/index.js +17 -0
- package/dist/url/params.d.ts +141 -0
- package/dist/{url.js → url/params.js} +90 -18
- package/dist/url/slug.d.ts +28 -0
- package/dist/url/slug.js +102 -0
- package/dist/veil.d.ts +14 -0
- package/dist/veil.js +26 -0
- package/dist/xod.d.ts +237 -16
- package/dist/xod.js +192 -18
- package/dist/zipper.d.ts +22 -4
- package/dist/zipper.js +22 -5
- package/package.json +82 -34
- package/dist/async/space.d.ts +0 -8
- package/dist/async/space.js +0 -31
- package/dist/cleanup.d.ts +0 -9
- package/dist/cleanup.js +0 -18
- package/dist/colors.d.ts +0 -539
- package/dist/colors.js +0 -888
- package/dist/cookie.d.ts +0 -60
- package/dist/cookie.js +0 -48
- package/dist/datetime.d.ts +0 -82
- package/dist/datetime.js +0 -161
- package/dist/format.d.ts +0 -36
- package/dist/format.js +0 -26
- package/dist/future.d.ts +0 -51
- package/dist/future.js +0 -71
- package/dist/html.d.ts +0 -145
- package/dist/html.js +0 -205
- package/dist/humanly.d.ts +0 -9
- package/dist/humanly.js +0 -93
- package/dist/lru.d.ts +0 -77
- package/dist/lru.js +0 -128
- package/dist/queue.d.ts +0 -40
- package/dist/queue.js +0 -56
- package/dist/url.d.ts +0 -61
package/dist/async/index.js
CHANGED
|
@@ -1,93 +1,98 @@
|
|
|
1
|
+
export const createManualPromise = () => {
|
|
2
|
+
let resolve;
|
|
3
|
+
let reject;
|
|
4
|
+
const promise = new Promise((res, rej) => {
|
|
5
|
+
resolve = res;
|
|
6
|
+
reject = rej;
|
|
7
|
+
});
|
|
8
|
+
return { resolve, promise, reject };
|
|
9
|
+
};
|
|
10
|
+
//...
|
|
1
11
|
/**
|
|
2
|
-
* Создаёт
|
|
12
|
+
* Создаёт промис, завершающийся через заданное время
|
|
13
|
+
*
|
|
14
|
+
* @param ms - Время задержки в миллисекундах
|
|
15
|
+
* @param [success=true] - Завершать успехом или отклонять
|
|
16
|
+
*
|
|
17
|
+
* @remarks При `success = false` промис отклоняется с ошибкой `"delay rejected"`
|
|
3
18
|
*/
|
|
4
|
-
export const delay = (ms, success = true) => new Promise((resolve, reject) => setTimeout(success ? resolve : reject, ms));
|
|
19
|
+
export const delay = (ms, success = true) => new Promise((resolve, reject) => setTimeout(() => (success ? resolve() : reject(new Error("delay rejected"))), ms));
|
|
5
20
|
/**
|
|
6
21
|
* Создаёт debounce-функцию, которая откладывает выполнение до тех пор, пока не пройдёт указанное время без новых вызовов
|
|
7
22
|
*
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
23
|
+
* @remarks Ошибки полностью игнорируются
|
|
24
|
+
* @remarks Если нужен результат, используйте {@link throttle}
|
|
10
25
|
*
|
|
11
|
-
* @
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const debouncedMethod = debounce(this.method.bind(this), 200);
|
|
29
|
+
* const debouncedFunc = debounce((value: string) => func(value), 300);
|
|
30
|
+
* ```
|
|
12
31
|
*/
|
|
13
|
-
export const debounce = (
|
|
32
|
+
export const debounce = (func, ms) => {
|
|
14
33
|
let timeout;
|
|
15
34
|
return (...args) => {
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
17
35
|
if (timeout)
|
|
18
36
|
clearTimeout(timeout);
|
|
19
|
-
timeout = setTimeout(() =>
|
|
37
|
+
timeout = setTimeout(() => void func(...args), ms);
|
|
20
38
|
};
|
|
21
39
|
};
|
|
22
40
|
/**
|
|
23
|
-
* Создаёт
|
|
24
|
-
*
|
|
41
|
+
* Создаёт throttle-функцию, которая вызывает переданную функцию не чаще одного раза в заданный интервал времени
|
|
42
|
+
*
|
|
43
|
+
* @param func - Функция для троттлинга
|
|
44
|
+
* @param [mode="urgent"] - Режим троттлинга
|
|
45
|
+
* @param [ms=250] - Интервал времени в миллисекундах
|
|
25
46
|
*
|
|
26
|
-
*
|
|
27
|
-
* - первый вызов откладывается на `ms`
|
|
28
|
-
* - повторные вызовы до старта игнорируются, аргументы обновляются
|
|
29
|
-
* - все ждут одного промисса
|
|
47
|
+
* @throws {unknown} Ошибки функции прокидываются в промис
|
|
30
48
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const throttledScroll = throttle((position) => saveScrollPosition(position), "delay", 100);
|
|
52
|
+
* window.addEventListener("scroll", () => void throttledScroll(window.scrollY)); // выполнится через 100 ms с самым последним scrollY
|
|
53
|
+
*
|
|
54
|
+
* const throttledFetch = throttle((id: string) => fetch(`/api/data/${id}`).then(r => r.json()), "urgent", 500);
|
|
55
|
+
* const result1 = await throttledFetch("123"); // Выполняется сразу с "123"
|
|
56
|
+
* const result2 = await throttledFetch("456"); // Возвращает тот же промис с "123"
|
|
57
|
+
* ```
|
|
35
58
|
*/
|
|
36
|
-
export const throttle = (
|
|
37
|
-
let _promise
|
|
59
|
+
export const throttle = (func, mode = "urgent", ms = 250) => {
|
|
60
|
+
let _promise;
|
|
38
61
|
let _args = [];
|
|
62
|
+
const call = async () => await func(..._args);
|
|
63
|
+
const reset = () => (_promise = null);
|
|
39
64
|
return (...args) => {
|
|
40
65
|
_args = args;
|
|
41
66
|
if (_promise)
|
|
42
67
|
return _promise;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
_promise = new Promise((resolve, reject) => {
|
|
46
|
-
resolver = resolve;
|
|
47
|
-
rejecter = reject;
|
|
48
|
-
});
|
|
49
|
-
const reset = () => (_promise = null);
|
|
68
|
+
const { resolve, reject, promise } = createManualPromise();
|
|
69
|
+
_promise = promise;
|
|
50
70
|
if (mode === "delay") {
|
|
51
71
|
setTimeout(() => {
|
|
52
|
-
call(
|
|
53
|
-
.then(resolver)
|
|
54
|
-
.catch(rejecter)
|
|
55
|
-
.finally(reset);
|
|
72
|
+
call().then(resolve).catch(reject).finally(reset);
|
|
56
73
|
}, ms);
|
|
57
74
|
}
|
|
58
75
|
else {
|
|
59
|
-
call(
|
|
60
|
-
.then(
|
|
61
|
-
.catch(
|
|
62
|
-
.finally(delay(ms).then(reset));
|
|
76
|
+
call()
|
|
77
|
+
.then(resolve)
|
|
78
|
+
.catch(reject)
|
|
79
|
+
.finally(() => void delay(ms).then(reset));
|
|
63
80
|
}
|
|
64
81
|
return _promise;
|
|
65
82
|
};
|
|
66
83
|
};
|
|
67
|
-
//...
|
|
68
84
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* При первом вызове запускает переданный `call` и сохраняет его результат.
|
|
72
|
-
* Все последующие вызовы возвращают сохранённый результат без повторного выполнения операции.
|
|
73
|
-
* Если вызов происходит во время выполнения, возвращает тот же промисс, вместо создания нового
|
|
74
|
-
*
|
|
75
|
-
* @param call - Асинхронная функция, результат которой нужно кешировать
|
|
76
|
-
* @returns Функция, возвращающая закешированный результат после первого успешного выполнения
|
|
85
|
+
* Приведение коллбэка к промису с отловом ошибок и fallback-значением
|
|
77
86
|
*/
|
|
78
|
-
export const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
promise = call().then((result) => {
|
|
87
|
-
value = result;
|
|
88
|
-
return result;
|
|
89
|
-
});
|
|
87
|
+
export const boundary = async (func, fallback) => {
|
|
88
|
+
try {
|
|
89
|
+
return await func();
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
if (typeof fallback === "function") {
|
|
93
|
+
// @ts-expect-error <тут не типизировать>
|
|
94
|
+
return fallback(e);
|
|
90
95
|
}
|
|
91
|
-
return
|
|
92
|
-
}
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
93
98
|
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Тип хука, возвращаемый методом {@link Loader.hook}
|
|
3
|
+
*/
|
|
4
|
+
export type LoaderHook = ReturnType<Loader["hook"]>;
|
|
5
|
+
/**
|
|
6
|
+
* Менеджер состояния выполнения для асинхронных операций
|
|
7
|
+
*
|
|
8
|
+
* Отслеживает активность через очередь промисов: состояние `true`, пока есть незавершённые промисы.
|
|
9
|
+
* Использует версионирование, чтобы избежать гонок при быстрых последовательных вызовах
|
|
10
|
+
*/
|
|
11
|
+
export declare class Loader {
|
|
12
|
+
__heap: Promise<unknown>[];
|
|
13
|
+
__version: number;
|
|
14
|
+
__onchange: (v: boolean) => void;
|
|
15
|
+
constructor(onchange: (v: boolean) => void);
|
|
16
|
+
reset(): void;
|
|
17
|
+
__reset(version: number): void;
|
|
18
|
+
__check(version: number): void;
|
|
19
|
+
__awaiter(version: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* Добавляет промис в очередь отслеживания
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* async function fetchData() {
|
|
26
|
+
* const promise = fetch("/api/data");
|
|
27
|
+
* loader.push(promise);
|
|
28
|
+
* const data = await promise;
|
|
29
|
+
* return data;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
push(promise: Promise<any>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Создаёт хук: возвращает функцию, которая завершает отслеживание при вызове
|
|
36
|
+
*
|
|
37
|
+
* Внутри создаётся промис, добавляемый в очередь. Вызов возвращённой функции разрешает его
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const complete = loader.hook();
|
|
42
|
+
* try {
|
|
43
|
+
* await someAsyncOperation();
|
|
44
|
+
* } finally {
|
|
45
|
+
* complete();
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
hook(): () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Выполняет функцию и автоматически отслеживает её промис
|
|
52
|
+
*
|
|
53
|
+
* @param func — Асинхронная функция для выполнения
|
|
54
|
+
* @param [external] — Опциональный коллбэк для синхронного уведомления о начале/завершении
|
|
55
|
+
*
|
|
56
|
+
* @throws {unknown} Ошибки промиса функции
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* async function fetchData() {
|
|
61
|
+
* const data = await loader.run(() => fetch("/api/data"));
|
|
62
|
+
* return data;
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
run<T = any>(func: () => Promise<T>, external?: (v: boolean) => void): Promise<T>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createManualPromise } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Менеджер состояния выполнения для асинхронных операций
|
|
4
|
+
*
|
|
5
|
+
* Отслеживает активность через очередь промисов: состояние `true`, пока есть незавершённые промисы.
|
|
6
|
+
* Использует версионирование, чтобы избежать гонок при быстрых последовательных вызовах
|
|
7
|
+
*/
|
|
8
|
+
export class Loader {
|
|
9
|
+
__heap = [];
|
|
10
|
+
__version = 0;
|
|
11
|
+
__onchange;
|
|
12
|
+
constructor(onchange) {
|
|
13
|
+
this.__onchange = onchange;
|
|
14
|
+
}
|
|
15
|
+
reset() {
|
|
16
|
+
this.__onchange(false);
|
|
17
|
+
this.__version = 0;
|
|
18
|
+
this.__heap = [];
|
|
19
|
+
}
|
|
20
|
+
//...
|
|
21
|
+
__reset(version) {
|
|
22
|
+
if (this.__version !== version)
|
|
23
|
+
return;
|
|
24
|
+
this.reset();
|
|
25
|
+
}
|
|
26
|
+
__check(version) {
|
|
27
|
+
if (this.__heap.length === 0)
|
|
28
|
+
return this.reset();
|
|
29
|
+
void Promise.allSettled(this.__heap).then(() => this.__reset(version));
|
|
30
|
+
}
|
|
31
|
+
__awaiter(version) {
|
|
32
|
+
this.__onchange(true);
|
|
33
|
+
this.__check(version);
|
|
34
|
+
}
|
|
35
|
+
//...
|
|
36
|
+
/**
|
|
37
|
+
* Добавляет промис в очередь отслеживания
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* async function fetchData() {
|
|
42
|
+
* const promise = fetch("/api/data");
|
|
43
|
+
* loader.push(promise);
|
|
44
|
+
* const data = await promise;
|
|
45
|
+
* return data;
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
push(promise) {
|
|
50
|
+
this.__version++;
|
|
51
|
+
this.__heap.push(promise);
|
|
52
|
+
this.__awaiter(this.__version);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Создаёт хук: возвращает функцию, которая завершает отслеживание при вызове
|
|
56
|
+
*
|
|
57
|
+
* Внутри создаётся промис, добавляемый в очередь. Вызов возвращённой функции разрешает его
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const complete = loader.hook();
|
|
62
|
+
* try {
|
|
63
|
+
* await someAsyncOperation();
|
|
64
|
+
* } finally {
|
|
65
|
+
* complete();
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
hook() {
|
|
70
|
+
const { promise, resolve } = createManualPromise();
|
|
71
|
+
this.push(promise);
|
|
72
|
+
return resolve;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Выполняет функцию и автоматически отслеживает её промис
|
|
76
|
+
*
|
|
77
|
+
* @param func — Асинхронная функция для выполнения
|
|
78
|
+
* @param [external] — Опциональный коллбэк для синхронного уведомления о начале/завершении
|
|
79
|
+
*
|
|
80
|
+
* @throws {unknown} Ошибки промиса функции
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* async function fetchData() {
|
|
85
|
+
* const data = await loader.run(() => fetch("/api/data"));
|
|
86
|
+
* return data;
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
async run(func, external) {
|
|
91
|
+
external?.(true);
|
|
92
|
+
try {
|
|
93
|
+
const promise = func();
|
|
94
|
+
this.push(promise);
|
|
95
|
+
return await promise;
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
external?.(false);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CanBePromise, TimeoutType } from "../types.js";
|
|
2
|
+
export type QueueHandler<T> = (item: T, abort: () => void) => CanBePromise;
|
|
3
|
+
/**
|
|
4
|
+
* Асинхронная очередь с последовательной обработкой и возможностью прерывания
|
|
5
|
+
*
|
|
6
|
+
* Элементы обрабатываются **по одному**, с заданной задержкой между ними.
|
|
7
|
+
* Обработка останавливается, если очередь пуста, и возобновляется при новом `push`.
|
|
8
|
+
* Функция-обработчик получает `abort`, чтобы прервать дальнейшую обработку (например, при ошибке).
|
|
9
|
+
*
|
|
10
|
+
* @template T - Тип элементов в очереди
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const queue = new Queue(async (url, abort) => {
|
|
15
|
+
* try {
|
|
16
|
+
* await fetch(url);
|
|
17
|
+
* } catch (e) {
|
|
18
|
+
* abort(); // прекращает обработку оставшихся URL
|
|
19
|
+
* }
|
|
20
|
+
* }, 50);
|
|
21
|
+
*
|
|
22
|
+
* queue.push("https://example.com/1");
|
|
23
|
+
* queue.push("https://example.com/2");
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class Queue<T> {
|
|
27
|
+
delay: number;
|
|
28
|
+
__queue: T[];
|
|
29
|
+
__timeout: TimeoutType | 0;
|
|
30
|
+
__handle: QueueHandler<T>;
|
|
31
|
+
/**
|
|
32
|
+
* @param handle - Основная функция для обработки очереди
|
|
33
|
+
* @param [delay=25] - Задержка (в миллисекундах) между обработкой элементов очереди
|
|
34
|
+
*/
|
|
35
|
+
constructor(handle: QueueHandler<T>, delay?: number);
|
|
36
|
+
/**
|
|
37
|
+
* Добавляет элемент в очередь и запускает обработку
|
|
38
|
+
*
|
|
39
|
+
* @param item - Элемент для добавления в очередь
|
|
40
|
+
* @param [run=true] - Запуск выполнения через {@link run}
|
|
41
|
+
*/
|
|
42
|
+
push(item: T, run?: boolean): void;
|
|
43
|
+
/**
|
|
44
|
+
* @param [delay=this.delay] - Задержка перед запуском шага очереди
|
|
45
|
+
*
|
|
46
|
+
* @remarks Саморекурсивно
|
|
47
|
+
*/
|
|
48
|
+
run(delay?: number): void;
|
|
49
|
+
stop(): void;
|
|
50
|
+
reset(): void;
|
|
51
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Асинхронная очередь с последовательной обработкой и возможностью прерывания
|
|
3
|
+
*
|
|
4
|
+
* Элементы обрабатываются **по одному**, с заданной задержкой между ними.
|
|
5
|
+
* Обработка останавливается, если очередь пуста, и возобновляется при новом `push`.
|
|
6
|
+
* Функция-обработчик получает `abort`, чтобы прервать дальнейшую обработку (например, при ошибке).
|
|
7
|
+
*
|
|
8
|
+
* @template T - Тип элементов в очереди
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const queue = new Queue(async (url, abort) => {
|
|
13
|
+
* try {
|
|
14
|
+
* await fetch(url);
|
|
15
|
+
* } catch (e) {
|
|
16
|
+
* abort(); // прекращает обработку оставшихся URL
|
|
17
|
+
* }
|
|
18
|
+
* }, 50);
|
|
19
|
+
*
|
|
20
|
+
* queue.push("https://example.com/1");
|
|
21
|
+
* queue.push("https://example.com/2");
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class Queue {
|
|
25
|
+
delay;
|
|
26
|
+
__queue = [];
|
|
27
|
+
__timeout = 0;
|
|
28
|
+
__handle;
|
|
29
|
+
/**
|
|
30
|
+
* @param handle - Основная функция для обработки очереди
|
|
31
|
+
* @param [delay=25] - Задержка (в миллисекундах) между обработкой элементов очереди
|
|
32
|
+
*/
|
|
33
|
+
constructor(handle, delay = 25) {
|
|
34
|
+
this.__handle = handle;
|
|
35
|
+
this.delay = delay;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Добавляет элемент в очередь и запускает обработку
|
|
39
|
+
*
|
|
40
|
+
* @param item - Элемент для добавления в очередь
|
|
41
|
+
* @param [run=true] - Запуск выполнения через {@link run}
|
|
42
|
+
*/
|
|
43
|
+
push(item, run = true) {
|
|
44
|
+
this.__queue.push(item);
|
|
45
|
+
if (run)
|
|
46
|
+
this.run();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @param [delay=this.delay] - Задержка перед запуском шага очереди
|
|
50
|
+
*
|
|
51
|
+
* @remarks Саморекурсивно
|
|
52
|
+
*/
|
|
53
|
+
run(delay = this.delay) {
|
|
54
|
+
this.stop();
|
|
55
|
+
const start = async () => {
|
|
56
|
+
if (this.__queue.length === 0)
|
|
57
|
+
return this.stop();
|
|
58
|
+
const item = this.__queue.shift();
|
|
59
|
+
let aborted = false;
|
|
60
|
+
try {
|
|
61
|
+
await this.__handle(item, () => (aborted = true));
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
if (!aborted)
|
|
65
|
+
this.__queue.length > 0 ? this.run() : this.stop();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
if (delay) {
|
|
69
|
+
this.__timeout = setTimeout(() => void start(), delay);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
void start();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
stop() {
|
|
76
|
+
if (this.__timeout)
|
|
77
|
+
clearTimeout(this.__timeout);
|
|
78
|
+
this.__timeout = 0;
|
|
79
|
+
}
|
|
80
|
+
reset() {
|
|
81
|
+
this.stop();
|
|
82
|
+
this.__queue.length = 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
package/dist/cases.d.ts
CHANGED
|
@@ -1,30 +1,40 @@
|
|
|
1
|
-
export type CaseResult<V, T> = (value: V | undefined, mutate: boolean) => T;
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* Результат обработки значения в case-функциях
|
|
4
3
|
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
4
|
+
* @template V - Тип преобразованного значения
|
|
5
|
+
* @template T - Тип возвращаемого значения
|
|
6
|
+
*
|
|
7
|
+
* @param value - Преобразованное значение или undefined если преобразование невозможно
|
|
8
|
+
* @param mutated - Флаг указывающий было ли значение преобразовано (true) или осталось исходным (false)
|
|
9
|
+
*/
|
|
10
|
+
export type CaseResult<V, T> = (value: V | undefined, mutated: boolean) => T;
|
|
11
|
+
/**
|
|
12
|
+
* Преобразует значение к строке
|
|
13
|
+
*
|
|
14
|
+
* - `string` → исходная строка, `mutated: false`
|
|
15
|
+
* - `number` → строка, `mutated: true`
|
|
16
|
+
* - `NaN` → `undefined`, `mutated: false`
|
|
17
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
9
18
|
*/
|
|
10
|
-
export declare const caseString: <T>(value: unknown,
|
|
19
|
+
export declare const caseString: <T>(value: unknown, callback: CaseResult<string, T>) => T;
|
|
11
20
|
/**
|
|
12
|
-
*
|
|
21
|
+
* Преобразует значение к числу
|
|
13
22
|
*
|
|
14
|
-
* - `number` → `
|
|
15
|
-
* - `string` → `
|
|
16
|
-
* - `
|
|
17
|
-
* - `
|
|
23
|
+
* - `number` (не NaN) → исходное число, `mutated: false`
|
|
24
|
+
* - `string` (числовая строка) → число, `mutated: true`
|
|
25
|
+
* - `number` (NaN) → `undefined`, `mutated: false`
|
|
26
|
+
* - `string` (пустая или нечисловая) → `undefined`, `mutated: false`
|
|
27
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
18
28
|
*/
|
|
19
|
-
export declare const caseNumber: <T>(value: unknown,
|
|
29
|
+
export declare const caseNumber: <T>(value: unknown, callback: CaseResult<number, T>) => T;
|
|
20
30
|
/**
|
|
21
|
-
*
|
|
31
|
+
* Преобразует значение к булеву типу
|
|
22
32
|
*
|
|
23
|
-
* - `boolean`
|
|
24
|
-
* - `
|
|
25
|
-
* - `
|
|
26
|
-
* - `
|
|
27
|
-
* - `
|
|
28
|
-
* - `ETC` → `undefined`, `false`
|
|
33
|
+
* - `boolean` → исходное значение, `mutated: false`
|
|
34
|
+
* - `number` (0) → `false`, `mutated: true`
|
|
35
|
+
* - `number` (1) → `true`, `mutated: true`
|
|
36
|
+
* - `string` ("false") → `false`, `mutated: true`
|
|
37
|
+
* - `string` ("true") → `true`, `mutated: true`
|
|
38
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
29
39
|
*/
|
|
30
|
-
export declare const caseBoolean: <T>(value: unknown,
|
|
40
|
+
export declare const caseBoolean: <T>(value: unknown, callback: CaseResult<boolean, T>) => T;
|
package/dist/cases.js
CHANGED
|
@@ -1,69 +1,73 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Преобразует значение к строке
|
|
3
3
|
*
|
|
4
|
-
* - `string` → `
|
|
5
|
-
* - `number` → `
|
|
6
|
-
* - `NaN` → `undefined`, `false`
|
|
7
|
-
* - `ETC` → `undefined`, `false`
|
|
4
|
+
* - `string` → исходная строка, `mutated: false`
|
|
5
|
+
* - `number` → строка, `mutated: true`
|
|
6
|
+
* - `NaN` → `undefined`, `mutated: false`
|
|
7
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
8
8
|
*/
|
|
9
|
-
export const caseString = (value,
|
|
9
|
+
export const caseString = (value, callback) => {
|
|
10
10
|
switch (typeof value) {
|
|
11
11
|
case "string":
|
|
12
|
-
return
|
|
12
|
+
return callback(value, false);
|
|
13
13
|
case "number":
|
|
14
14
|
if (!isNaN(value))
|
|
15
|
-
return
|
|
15
|
+
return callback(String(value), true);
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return callback(undefined, false);
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Преобразует значение к числу
|
|
21
21
|
*
|
|
22
|
-
* - `number` → `
|
|
23
|
-
* - `string` → `
|
|
24
|
-
* - `
|
|
25
|
-
* - `
|
|
22
|
+
* - `number` (не NaN) → исходное число, `mutated: false`
|
|
23
|
+
* - `string` (числовая строка) → число, `mutated: true`
|
|
24
|
+
* - `number` (NaN) → `undefined`, `mutated: false`
|
|
25
|
+
* - `string` (пустая или нечисловая) → `undefined`, `mutated: false`
|
|
26
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
26
27
|
*/
|
|
27
|
-
export const caseNumber = (value,
|
|
28
|
+
export const caseNumber = (value, callback) => {
|
|
28
29
|
switch (typeof value) {
|
|
29
30
|
case "number":
|
|
30
|
-
return
|
|
31
|
+
return callback(isNaN(value) ? undefined : value, false);
|
|
31
32
|
case "string": {
|
|
32
33
|
const trimmed = value.trim();
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
34
|
+
// Проверяем что строка не пустая и преобразуется в валидное число
|
|
35
|
+
if (trimmed !== "") {
|
|
36
|
+
const number = Number(trimmed);
|
|
37
|
+
if (!isNaN(number))
|
|
38
|
+
return callback(number, true);
|
|
39
|
+
}
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
|
-
return
|
|
42
|
+
return callback(undefined, false);
|
|
39
43
|
};
|
|
40
44
|
/**
|
|
41
|
-
*
|
|
45
|
+
* Преобразует значение к булеву типу
|
|
42
46
|
*
|
|
43
|
-
* - `boolean`
|
|
44
|
-
* - `
|
|
45
|
-
* - `
|
|
46
|
-
* - `
|
|
47
|
-
* - `
|
|
48
|
-
* - `ETC` → `undefined`, `false`
|
|
47
|
+
* - `boolean` → исходное значение, `mutated: false`
|
|
48
|
+
* - `number` (0) → `false`, `mutated: true`
|
|
49
|
+
* - `number` (1) → `true`, `mutated: true`
|
|
50
|
+
* - `string` ("false") → `false`, `mutated: true`
|
|
51
|
+
* - `string` ("true") → `true`, `mutated: true`
|
|
52
|
+
* - `ETC` → `undefined`, `mutated: false`
|
|
49
53
|
*/
|
|
50
|
-
export const caseBoolean = (value,
|
|
54
|
+
export const caseBoolean = (value, callback) => {
|
|
51
55
|
switch (typeof value) {
|
|
52
56
|
case "boolean":
|
|
53
|
-
return
|
|
57
|
+
return callback(value, false);
|
|
54
58
|
case "number":
|
|
55
59
|
if (value === 0)
|
|
56
|
-
return
|
|
60
|
+
return callback(false, true);
|
|
57
61
|
if (value === 1)
|
|
58
|
-
return
|
|
62
|
+
return callback(true, true);
|
|
59
63
|
break;
|
|
60
64
|
case "string": {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
return
|
|
64
|
-
if (
|
|
65
|
-
return
|
|
65
|
+
const normalized = value.trim().toLowerCase();
|
|
66
|
+
if (normalized === "false")
|
|
67
|
+
return callback(false, true);
|
|
68
|
+
if (normalized === "true")
|
|
69
|
+
return callback(true, true);
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
|
-
return
|
|
72
|
+
return callback(undefined, false);
|
|
69
73
|
};
|