semantic-typescript 0.7.0 → 0.8.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/asynchronous/semantic.d.ts +4 -0
- package/dist/asynchronous/semantic.js +3 -0
- package/dist/factory.d.ts +24 -71
- package/dist/factory.js +161 -648
- package/dist/guard.d.ts +0 -3
- package/dist/guard.js +0 -19
- package/dist/hash.js +3 -0
- package/dist/synchronous/semantic.d.ts +4 -0
- package/dist/synchronous/semantic.js +26 -7
- package/package.json +2 -2
- package/readme.cn.md +185 -131
- package/readme.de.md +186 -132
- package/readme.es.md +186 -132
- package/readme.fr.md +188 -134
- package/readme.jp.md +185 -140
- package/readme.kr.md +184 -139
- package/readme.md +187 -130
- package/readme.ru.md +186 -143
- package/readme.tw.md +190 -146
- package/dist/main.d.ts +0 -1
- package/dist/main.js +0 -6
package/dist/guard.d.ts
CHANGED
|
@@ -37,6 +37,3 @@ export declare let isPromise: (target: unknown) => target is Promise<unknown>;
|
|
|
37
37
|
export declare let isAsyncFunction: (target: unknown) => target is AsyncFunction;
|
|
38
38
|
export declare let isGeneratorFunction: (target: unknown) => target is Generator<unknown, unknown, unknown>;
|
|
39
39
|
export declare let isAsyncGeneratorFunction: (target: unknown) => target is AsyncGenerator<unknown, unknown, unknown>;
|
|
40
|
-
export declare let isWindow: (target: unknown) => target is Window;
|
|
41
|
-
export declare let isDocument: (target: unknown) => target is Document;
|
|
42
|
-
export declare let isHTMLElemet: (target: unknown) => target is HTMLElement;
|
package/dist/guard.js
CHANGED
|
@@ -173,22 +173,3 @@ export let isAsyncGeneratorFunction = (target) => {
|
|
|
173
173
|
}
|
|
174
174
|
return false;
|
|
175
175
|
};
|
|
176
|
-
export let isWindow = (target) => {
|
|
177
|
-
if (isObject(target) && isObject(Reflect.get(target, "window"))) {
|
|
178
|
-
return Object.prototype.toString.call(Reflect.get(target, "window")) === "[object Window]";
|
|
179
|
-
}
|
|
180
|
-
return false;
|
|
181
|
-
};
|
|
182
|
-
export let isDocument = (target) => {
|
|
183
|
-
if (isObject(target) && isObject(Reflect.get(target, "document"))) {
|
|
184
|
-
return Object.prototype.toString.call(Reflect.get(target, "document")) === "[object HTMLDocument]";
|
|
185
|
-
}
|
|
186
|
-
return false;
|
|
187
|
-
};
|
|
188
|
-
export let isHTMLElemet = (target) => {
|
|
189
|
-
if (isObject(target)) {
|
|
190
|
-
let regex = /^\[object HTML\w+Element\]$/;
|
|
191
|
-
return regex.test(Object.prototype.toString.call(target));
|
|
192
|
-
}
|
|
193
|
-
return false;
|
|
194
|
-
};
|
package/dist/hash.js
CHANGED
|
@@ -70,6 +70,9 @@ register("number", (value) => {
|
|
|
70
70
|
if (primitive.has(value)) {
|
|
71
71
|
return primitive.get(value) || 0n;
|
|
72
72
|
}
|
|
73
|
+
if (Number.isNaN(value)) {
|
|
74
|
+
return 0x7ff8000000000000n;
|
|
75
|
+
}
|
|
73
76
|
let mask = maskOf("number");
|
|
74
77
|
let bit = 0xffffffffffffffffn;
|
|
75
78
|
let buffer = new ArrayBuffer(8);
|
|
@@ -25,6 +25,8 @@ export declare class SynchronousSemantic<E> {
|
|
|
25
25
|
flatMap<R>(mapper: BiFunctional<E, bigint, SynchronousSemantic<R>>): SynchronousSemantic<R>;
|
|
26
26
|
limit(count: number): SynchronousSemantic<E>;
|
|
27
27
|
limit(count: bigint): SynchronousSemantic<E>;
|
|
28
|
+
map(mapper: Functional<E, E>): SynchronousSemantic<E>;
|
|
29
|
+
map(mapper: BiFunctional<E, bigint, E>): SynchronousSemantic<E>;
|
|
28
30
|
map<R>(mapper: Functional<E, R>): SynchronousSemantic<R>;
|
|
29
31
|
map<R>(mapper: BiFunctional<E, bigint, R>): SynchronousSemantic<R>;
|
|
30
32
|
peek(consumer: Consumer<E>): SynchronousSemantic<E>;
|
|
@@ -106,6 +108,8 @@ export declare abstract class SynchronousCollectable<E> implements Iterable<E> {
|
|
|
106
108
|
partition(count: bigint): Array<Array<E>>;
|
|
107
109
|
partitionBy(classifier: Functional<E, bigint>): Array<Array<E>>;
|
|
108
110
|
partitionBy(classifier: BiFunctional<E, bigint, bigint>): Array<Array<E>>;
|
|
111
|
+
pipe(conversion: Functional<SynchronousGenerator<E>, SynchronousSemantic<E>>): SynchronousSemantic<E>;
|
|
112
|
+
pipe<R>(conversion: Functional<SynchronousGenerator<E>, SynchronousSemantic<R>>): SynchronousSemantic<R>;
|
|
109
113
|
reduce(accumulator: BiFunctional<E, E, E>): E;
|
|
110
114
|
reduce(accumulator: TriFunctional<E, E, bigint, E>): E;
|
|
111
115
|
reduce(identity: E, accumulator: BiFunctional<E, E, E>): E;
|
|
@@ -99,6 +99,7 @@ export class SynchronousSemantic {
|
|
|
99
99
|
this.generator((element, index) => {
|
|
100
100
|
if (count === -1n) {
|
|
101
101
|
if (!predicate(element, index)) {
|
|
102
|
+
accept(element, count);
|
|
102
103
|
count++;
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -269,9 +270,14 @@ export class SynchronousSemantic {
|
|
|
269
270
|
if (isFunction(redirector)) {
|
|
270
271
|
return new SynchronousSemantic((accept, interrupt) => {
|
|
271
272
|
try {
|
|
273
|
+
let stop = false;
|
|
272
274
|
this.generator((element, index) => {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
+
let redirected = redirector(element, index);
|
|
276
|
+
stop = stop || interrupt(element, redirected);
|
|
277
|
+
accept(element, redirected);
|
|
278
|
+
}, () => {
|
|
279
|
+
return stop;
|
|
280
|
+
});
|
|
275
281
|
}
|
|
276
282
|
catch (error) {
|
|
277
283
|
throw error;
|
|
@@ -283,9 +289,14 @@ export class SynchronousSemantic {
|
|
|
283
289
|
reverse() {
|
|
284
290
|
return new SynchronousSemantic((accept, interrupt) => {
|
|
285
291
|
try {
|
|
292
|
+
let stop = false;
|
|
286
293
|
this.generator((element, index) => {
|
|
287
|
-
|
|
288
|
-
|
|
294
|
+
let redirected = -index;
|
|
295
|
+
stop = stop || interrupt(element, redirected);
|
|
296
|
+
accept(element, redirected);
|
|
297
|
+
}, () => {
|
|
298
|
+
return stop;
|
|
299
|
+
});
|
|
289
300
|
}
|
|
290
301
|
catch (error) {
|
|
291
302
|
throw error;
|
|
@@ -296,9 +307,14 @@ export class SynchronousSemantic {
|
|
|
296
307
|
if (isFunction(mapper)) {
|
|
297
308
|
return new SynchronousSemantic((accept, interrupt) => {
|
|
298
309
|
try {
|
|
310
|
+
let stop = false;
|
|
299
311
|
this.generator((element, index) => {
|
|
300
|
-
|
|
301
|
-
|
|
312
|
+
let redirected = mapper(element, index);
|
|
313
|
+
stop = stop || interrupt(element, redirected);
|
|
314
|
+
accept(element, redirected);
|
|
315
|
+
}, () => {
|
|
316
|
+
return stop;
|
|
317
|
+
});
|
|
302
318
|
}
|
|
303
319
|
catch (error) {
|
|
304
320
|
throw error;
|
|
@@ -389,7 +405,7 @@ export class SynchronousSemantic {
|
|
|
389
405
|
try {
|
|
390
406
|
let stop = false;
|
|
391
407
|
this.generator((element, index) => {
|
|
392
|
-
if (predicate(element, index) && stop
|
|
408
|
+
if (predicate(element, index) && (!stop)) {
|
|
393
409
|
accept(element, index);
|
|
394
410
|
}
|
|
395
411
|
else {
|
|
@@ -801,6 +817,9 @@ export class SynchronousCollectable {
|
|
|
801
817
|
}
|
|
802
818
|
throw new TypeError("Classifier must be a function.");
|
|
803
819
|
}
|
|
820
|
+
pipe(conversion) {
|
|
821
|
+
return conversion(this.source());
|
|
822
|
+
}
|
|
804
823
|
reduce(argument1, argument2, argument3) {
|
|
805
824
|
if (isFunction(argument1) && invalidate(argument2) && invalidate(argument3)) {
|
|
806
825
|
try {
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/eloyhere"
|
|
7
7
|
},
|
|
8
8
|
"description": "A modern type-safe stream processing library inspired by JavaScript Generator, Java Stream, and MySQL Index. Supports lazy evaluation, async streams, statistics, and IO-like operations.",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.8.0",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"readme": "readme.md",
|
|
12
12
|
"main": "dist/index.js",
|
|
@@ -55,4 +55,4 @@
|
|
|
55
55
|
"build": "tsc",
|
|
56
56
|
"prepublishOnly": "npm run build"
|
|
57
57
|
}
|
|
58
|
-
}
|
|
58
|
+
}
|
package/readme.cn.md
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
# **Semantic
|
|
2
|
-
|
|
1
|
+
# **Semantic‑TypeScript**
|
|
2
|
+
**流处理,索引化。** 让您的数据处于精准控制之下。
|
|
3
3
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
### 概述
|
|
7
7
|
|
|
8
|
-
Semantic
|
|
8
|
+
Semantic‑TypeScript 代表了流处理领域的一次重大演进,它巧妙地**融合**了 JavaScript 生成器、Java Streams 和 MySQL 风格索引中最有效的范式。其核心理念强大而明确:通过智能索引而非传统的蛮力迭代,构建极其高效的数据处理管道。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
传统的库通常强制使用同步循环或笨重的 Promise 链,而 Semantic‑TypeScript 则提供了一个**完全异步**、函数式纯正且类型绝对安全的体验,专为满足现代应用程序开发的需求而设计。
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
该模型体现了一种精炼的控制流:数据仅在上游管道显式调用 `accept` 回调时,才会传递给下游消费者。您可以对处理时机保持完全、细粒度的掌控——处理仅在需要时、且仅在要求的时刻发生。
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
###
|
|
16
|
+
### 开发者为何选择 Semantic‑TypeScript
|
|
17
17
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- **无未定义行为**
|
|
18
|
+
- **零模板索引** – 每个元素天生拥有其自然或自定义的索引,无需手动跟踪。
|
|
19
|
+
- **纯函数式与类型安全** – 在支持不可变操作的同时,享受完整、地道的 TypeScript 类型推断。
|
|
20
|
+
- **无泄漏的事件流** – `useSubscription` 模式将资源安全作为首要原则设计。您通过 `limit(n)`、`sub(start, end)` 或 `takeWhile(predicate)` 定义逻辑边界,库则管理完整的订阅生命周期,确保没有残留的监听器和内存泄漏。
|
|
21
|
+
- **内置统计套件** – 无需外部依赖,即可访问针对 `number` 和 `bigint` 流的全面分析功能,包括平均值、中位数、众数、方差、偏度和峰度。
|
|
22
|
+
- **可预测、可调优的性能** – 根据您对性能和顺序的精确需求,选择有序或无序收集器。
|
|
23
|
+
- **天然的内存高效** – 流采用惰性求值,按需处理元素以减轻内存压力。
|
|
24
|
+
- **无未定义行为** – TypeScript 保证完整的类型安全性和可空性。除非在回调函数中显式修改,否则您的源数据保持不变。
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
28
|
### 安装
|
|
29
29
|
|
|
30
|
+
使用您偏好的包管理器将 Semantic‑TypeScript 集成到项目中:
|
|
31
|
+
|
|
30
32
|
```bash
|
|
31
33
|
npm install semantic-typescript
|
|
32
34
|
```
|
|
@@ -37,177 +39,229 @@ yarn add semantic-typescript
|
|
|
37
39
|
|
|
38
40
|
---
|
|
39
41
|
|
|
40
|
-
###
|
|
42
|
+
### 快速入门
|
|
43
|
+
|
|
44
|
+
以下示例演示了从基础转换到实际事件处理的核心概念。
|
|
41
45
|
|
|
42
46
|
```typescript
|
|
43
|
-
import { useOf, useFrom, useRange,
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
.
|
|
47
|
+
import { useOf, useFrom, useRange, useSubscription, useText, useStringify } from "semantic-typescript";
|
|
48
|
+
|
|
49
|
+
// ====================================================================
|
|
50
|
+
// 示例 1: 基础操作与数值统计
|
|
51
|
+
// ====================================================================
|
|
52
|
+
// 演示映射和终端统计操作。转换后,管道必须转换为统计收集器才能调用 `.summate()` 等终端方法。
|
|
53
|
+
|
|
54
|
+
const numericSum: number = useOf(10, 20, 30, 40)
|
|
55
|
+
.map((n: number): number => n * 2) // 每个元素翻倍: [20, 40, 60, 80]
|
|
56
|
+
.toNumericStatistics() // 转换为统计收集器
|
|
57
|
+
.summate(); // 终端操作: 200
|
|
58
|
+
|
|
59
|
+
// 其他统计方法(在 .toNumericStatistics() 后可用):
|
|
60
|
+
// .average(), .median(), .mode(), .variance(), .skewness(), .kurtosis()
|
|
61
|
+
|
|
62
|
+
// ====================================================================
|
|
63
|
+
// 示例 2: BigInt 统计
|
|
64
|
+
// ====================================================================
|
|
65
|
+
// 与数值统计操作相同,但针对 BigInt 数据进行了优化。
|
|
66
|
+
|
|
67
|
+
const bigintSum: bigint = useOf(10n, 20n, 30n, 40n)
|
|
68
|
+
.map((n: bigint): bigint => n * 2n) // BigInt 算术
|
|
69
|
+
.toBigIntStatistics() // 转换为 BigInt 统计收集器
|
|
70
|
+
.summate(); // 终端操作: 200n
|
|
71
|
+
|
|
72
|
+
// ====================================================================
|
|
73
|
+
// 示例 3: 通过索引操作实现流反转
|
|
74
|
+
// ====================================================================
|
|
75
|
+
// 使用 `.redirect()` 方法通过策略性地重新分配元素索引来说明如何重新排序元素,从而实现反转等自定义模式。
|
|
76
|
+
|
|
77
|
+
const reversedArray: number[] = useFrom([1, 2, 3, 4, 5])
|
|
78
|
+
.redirect((_element: number, index: bigint): bigint => -index) // 映射到负索引
|
|
79
|
+
.toOrdered() // 关键步骤:按新索引收集并排序元素
|
|
80
|
+
.toArray(); // 结果: [5, 4, 3, 2, 1]
|
|
81
|
+
|
|
82
|
+
// 对于简单的反转,`.reverse()` 方法同样可用。
|
|
83
|
+
|
|
84
|
+
// ====================================================================
|
|
85
|
+
// 示例 4: 流洗牌
|
|
86
|
+
// ====================================================================
|
|
87
|
+
// 使用原地洗牌算法随机置换元素索引。
|
|
88
|
+
|
|
89
|
+
const shuffledArray: number[] = useFrom([1, 2, 3, 4, 5])
|
|
90
|
+
.shuffle() // 随机重新分配索引
|
|
91
|
+
.toOrdered() // 按新的随机索引排序
|
|
92
|
+
.toArray(); // 例如: [2, 5, 1, 4, 3] (每次执行结果不同)
|
|
93
|
+
|
|
94
|
+
// ====================================================================
|
|
95
|
+
// 示例 5: 循环流旋转
|
|
96
|
+
// ====================================================================
|
|
97
|
+
// 循环移动元素。正值向右旋转;负值向左旋转。
|
|
98
|
+
|
|
99
|
+
// 向右旋转 2 个位置
|
|
100
|
+
const rightRotated: number[] = useFrom([1, 2, 3, 4, 5])
|
|
101
|
+
.translate(2) // 将索引向右移动 2
|
|
66
102
|
.toOrdered()
|
|
67
|
-
.toArray();
|
|
103
|
+
.toArray(); // 结果: [4, 5, 1, 2, 3]
|
|
68
104
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.toArray(); // [4, 5, 1, 2, 3]
|
|
105
|
+
// ====================================================================
|
|
106
|
+
// 示例 6: 无限范围的惰性求值
|
|
107
|
+
// ====================================================================
|
|
108
|
+
// 惰性地处理理论上的无限流,仅在需要时计算元素。
|
|
74
109
|
|
|
75
|
-
|
|
76
|
-
.
|
|
77
|
-
.
|
|
78
|
-
.
|
|
110
|
+
const firstTenMultiples: bigint[] = useRange(0n, 1_000_000n)
|
|
111
|
+
.filter(n => n % 17n === 0n) // 保留 17 的倍数
|
|
112
|
+
.limit(10n) // 关键:在第 10 个匹配项后停止
|
|
113
|
+
.toUnordered() // 不需要排序
|
|
114
|
+
.toArray(); // 结果: [0, 17, 34, 51, 68, 85, 102, 119, 136, 153]
|
|
79
115
|
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
116
|
+
// 没有 `.limit(10n)` 的话,管道将处理所有一百万个元素。
|
|
117
|
+
|
|
118
|
+
// ====================================================================
|
|
119
|
+
// 示例 7: 组合复杂管道
|
|
120
|
+
// ====================================================================
|
|
121
|
+
// 演示多个操作的顺序组合。
|
|
122
|
+
|
|
123
|
+
const complexResult: number[] = useRange(1n, 100n)
|
|
124
|
+
.map(n => Number(n) * 2)
|
|
125
|
+
.filter(n => n > 50)
|
|
126
|
+
.shuffle()
|
|
127
|
+
.limit(5n)
|
|
128
|
+
.translate(2)
|
|
129
|
+
.toOrdered()
|
|
85
130
|
.toArray();
|
|
86
131
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
132
|
+
// ====================================================================
|
|
133
|
+
// 示例 8: 托管 DOM 事件订阅
|
|
134
|
+
// ====================================================================
|
|
135
|
+
// 监听浏览器事件,并附带自动、无泄漏的清理功能。
|
|
136
|
+
// `.limit(n)` 调用定义了自动移除监听器的边界。
|
|
137
|
+
|
|
138
|
+
// 为 Window 目标定义一个订阅者
|
|
139
|
+
const windowSubscriber = {
|
|
140
|
+
mount: (target: Window): void => { /* 设置逻辑 */ },
|
|
141
|
+
subscribe: (target: Window, event: keyof WindowEventMap, handler: EventListener): void => {
|
|
142
|
+
target.addEventListener(event, handler);
|
|
143
|
+
},
|
|
144
|
+
unsubscribe: (target: Window, event: keyof WindowEventMap, handler: EventListener): void => {
|
|
145
|
+
target.removeEventListener(event, handler);
|
|
146
|
+
},
|
|
147
|
+
unmount: (): void => { /* 清理逻辑 */ }
|
|
148
|
+
};
|
|
92
149
|
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
useHTMLElement("#input", "change")
|
|
96
|
-
.limit(1)
|
|
150
|
+
useSubscription(window, windowSubscriber, "resize")
|
|
151
|
+
.limit(5n) // 5 个事件后自动取消订阅
|
|
97
152
|
.toUnordered()
|
|
98
|
-
.forEach((
|
|
153
|
+
.forEach((ev: Event, idx) =>
|
|
154
|
+
console.log(`调整大小 #${idx}: ${(ev.target as Window).innerWidth}x${(ev.target as Window).innerHeight}`)
|
|
155
|
+
);
|
|
99
156
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.forEach((event: Event) => submit(event));
|
|
105
|
-
|
|
106
|
-
// 监听 WebSocket
|
|
107
|
-
let webSocket = new WebSocket("ws://localhost:8080");
|
|
108
|
-
webSocket.addEventListener("close", (): void => {
|
|
109
|
-
webSocket.close(); // 需手动管理 WebSocket 生命周期
|
|
110
|
-
});
|
|
111
|
-
useWebSocket(webSocket, "message")
|
|
112
|
-
.limit(1)
|
|
113
|
-
.toUnordered()
|
|
114
|
-
.forEach((message: MessageEvent) => console.log(message.data));
|
|
157
|
+
// ====================================================================
|
|
158
|
+
// 示例 9: 按 Unicode 码点处理字符串
|
|
159
|
+
// ====================================================================
|
|
160
|
+
// 正确遍历字符串,处理多字节 Unicode 字符。
|
|
115
161
|
|
|
116
|
-
// 按码点迭代字符串
|
|
117
162
|
useText("My emotion now is: 😊, and semantic is 👍")
|
|
118
163
|
.toUnordered()
|
|
119
|
-
.log(); //
|
|
164
|
+
.log(); // 将每个字符(包括表情符号)在新行打印。
|
|
120
165
|
|
|
121
|
-
//
|
|
122
|
-
|
|
166
|
+
// ====================================================================
|
|
167
|
+
// 示例 10: 安全的循环引用字符串化
|
|
168
|
+
// ====================================================================
|
|
169
|
+
// 安全地序列化包含循环引用的对象。
|
|
170
|
+
|
|
171
|
+
const obj = {
|
|
123
172
|
a: 1,
|
|
124
|
-
b: "text"
|
|
125
|
-
c: [o.a, o.b, o.c] // 循环引用
|
|
173
|
+
b: "text"
|
|
126
174
|
};
|
|
127
|
-
|
|
128
|
-
|
|
175
|
+
(obj as any).c = [obj.a, obj.b, (obj as any).c]; // 引入循环引用
|
|
176
|
+
|
|
177
|
+
// const text: string = JSON.stringify(obj); // 抛出错误
|
|
178
|
+
const text: string = useStringify(obj); // 安全地产生 `{a: 1, b: "text", c: []}`
|
|
129
179
|
```
|
|
130
180
|
|
|
131
181
|
---
|
|
132
182
|
|
|
133
183
|
### 核心概念
|
|
134
184
|
|
|
135
|
-
| 概念 | 目的 |
|
|
185
|
+
| 概念 | 目的 | 主要使用场景 |
|
|
136
186
|
| :--- | :--- | :--- |
|
|
137
|
-
| `AsynchronousSemantic` |
|
|
138
|
-
| `SynchronousSemantic` |
|
|
139
|
-
| `toUnordered()` |
|
|
140
|
-
| `toOrdered()` |
|
|
141
|
-
| `toNumericStatistics()` |
|
|
142
|
-
| `toBigIntStatistics()` |
|
|
143
|
-
| `toWindow()` |
|
|
187
|
+
| `AsynchronousSemantic` | 用于异步流、事件和基于推送的惰性管道的核心构建器。 | 实时事件、WebSockets、DOM 监听器或任何长时间运行/无限流。 |
|
|
188
|
+
| `SynchronousSemantic` | 用于同步、内存中或基于拉取的急切流的构建器。 | 静态数据、有限范围或需要立即迭代的任务。 |
|
|
189
|
+
| `toUnordered()` | 最快的终端收集器,使用 Map 存储索引。 | 性能关键路径,且不需要稳定顺序的场景(O(n) 时间和空间)。 |
|
|
190
|
+
| `toOrdered()` | 有序、索引稳定的终端收集器。 | 当需要保持元素顺序或需要索引访问时。 |
|
|
191
|
+
| `toNumericStatistics()` | 启用对 `number` 流进行丰富统计分析功能的收集器。 | 数据分析、指标和统计计算。 |
|
|
192
|
+
| `toBigIntStatistics()` | 启用对 `bigint` 流进行丰富统计分析功能的收集器。 | 大型整数数据集的分析和统计。 |
|
|
193
|
+
| `toWindow()` | 提供对流进行滑动和滚动窗口操作的功能。 | 时间序列分析、批处理和窗口聚合。 |
|
|
144
194
|
|
|
145
195
|
---
|
|
146
196
|
|
|
147
|
-
|
|
197
|
+
**基本使用规则**
|
|
148
198
|
|
|
149
|
-
1.
|
|
150
|
-
→
|
|
199
|
+
1. **事件流**(通过 `useSubscription` 等工厂函数创建)返回一个 `AsynchronousSemantic`。
|
|
200
|
+
→ 您**必须**调用一个定义边界的方法,如 `.limit(n)`、`.sub(start, end)` 或 `.takeWhile(predicate)` 来终止监听器。否则订阅将保持活动状态。
|
|
151
201
|
|
|
152
|
-
2.
|
|
202
|
+
2. **终端操作**(`.toArray()`、`.count()`、`.forEach()`、`.findFirst()` 等)**仅在**将管道转换为收集器**之后**可用:
|
|
153
203
|
```typescript
|
|
154
|
-
.toUnordered() //
|
|
204
|
+
.toUnordered() // 用于最大速度,不保证顺序。
|
|
155
205
|
// 或
|
|
156
|
-
.toOrdered() //
|
|
206
|
+
.toOrdered() // 用于稳定、有序的输出。
|
|
207
|
+
// 或
|
|
208
|
+
.toNumericStatistics() // 用于统计方法。
|
|
157
209
|
```
|
|
158
210
|
|
|
159
211
|
---
|
|
160
212
|
|
|
161
213
|
### 性能特征
|
|
162
214
|
|
|
163
|
-
| 收集器 | 时间复杂度 | 空间复杂度 |
|
|
215
|
+
| 收集器 | 时间复杂度 | 空间复杂度 | 保证顺序? | 理想场景 |
|
|
164
216
|
| :--- | :--- | :--- | :--- | :--- |
|
|
165
|
-
| `toUnordered()` | O(n) | O(n) | 否 |
|
|
166
|
-
| `toOrdered()` | O(
|
|
167
|
-
| `toNumericStatistics()` | O(
|
|
168
|
-
| `toBigIntStatistics()` | O(
|
|
169
|
-
| `toWindow()` | O(
|
|
217
|
+
| `toUnordered()` | O(n) | O(n) | 否 | 原始吞吐量是关键;最终顺序无关紧要。 |
|
|
218
|
+
| `toOrdered()` | O(n log n) | O(n) | 是(已排序) | 需要稳定顺序、索引访问或为统计进行预排序。 |
|
|
219
|
+
| `toNumericStatistics()` | O(n log n) | O(n) | 是(内部排序) | 执行需要排序数据的统计操作。 |
|
|
220
|
+
| `toBigIntStatistics()` | O(n log n) | O(n) | 是(内部排序) | 对 BigInt 数据进行统计操作。 |
|
|
221
|
+
| `toWindow()` | O(n log n) | O(n) | 是(内部排序) | 能从排序索引中受益的窗口操作。 |
|
|
170
222
|
|
|
171
|
-
|
|
223
|
+
当绝对速度至关重要时,选择 `toUnordered()`。仅当您的逻辑依赖于元素顺序时,才选择 `toOrdered()` 或统计收集器。
|
|
172
224
|
|
|
173
225
|
---
|
|
174
226
|
|
|
175
|
-
|
|
227
|
+
**与现代流处理库的对比分析**
|
|
176
228
|
|
|
177
|
-
| 特性 | Semantic
|
|
229
|
+
| 特性 | Semantic‑TypeScript | RxJS | 原生 Async Iterators / Generators | Most.js |
|
|
178
230
|
| :--- | :--- | :--- | :--- | :--- |
|
|
179
|
-
| **TypeScript 集成** |
|
|
180
|
-
| **内置统计分析** | 对 `number` 和 `bigint`
|
|
181
|
-
| **索引与位置感知** |
|
|
182
|
-
| **事件流管理** |
|
|
183
|
-
|
|
|
184
|
-
| **包体积** | 非常轻量。 |
|
|
185
|
-
| **API 设计理念** |
|
|
186
|
-
|
|
|
187
|
-
| **同步与异步支持** | 统一的 API
|
|
188
|
-
| **学习曲线** |
|
|
231
|
+
| **TypeScript 集成** | 一等公民,深度类型化,具有固有的索引感知。 | 优秀,但通常涉及复杂的泛型链。 | 良好,但需要手动类型注解。 | 强大,采用函数优先的编码风格。 |
|
|
232
|
+
| **内置统计分析** | 对 `number` 和 `bigint` 提供全面的原生支持。 | 非原生支持(需要自定义操作符或其他库)。 | 无。 | 无。 |
|
|
233
|
+
| **索引与位置感知** | 原生、强大的 BigInt 索引,每个元素都具备。 | 需要自定义操作符(如 `scan`、`withLatestFrom`)。 | 需要手动管理计数器。 | 基础,无内置索引属性。 |
|
|
234
|
+
| **事件流管理** | 专用的、类型安全的工厂,具有显式、声明式的生命周期控制。 | 强大,但需要谨慎的手动订阅管理以防止泄漏。 | 手动事件监听器附加和取消令牌管理。 | 良好的 `fromEvent`,通常较轻量。 |
|
|
235
|
+
| **性能与内存** | 卓越 – 提供优化的 `toUnordered()` 和 `toOrdered()` 收集器。 | 非常好,但深度操作符链可能引入开销。 | 优秀(最小的原生开销)。 | 优秀。 |
|
|
236
|
+
| **包体积** | 非常轻量。 | 较大(即使有 tree-shaking)。 | 零(原生语言特性)。 | 小。 |
|
|
237
|
+
| **API 设计理念** | 具有显式索引语义的函数式收集器模式。 | 响应式 Observable 模式。 | 命令式 Iterator / 声明式 Generator 模式。 | 函数式、无点组合。 |
|
|
238
|
+
| **流控制** | 显式(`interrupt`、`.limit()`、`.takeWhile()`、`.sub()`)。 | 良好(`take`、`takeUntil`、`first`)。 | 手动(循环中的 `break`)。 | 良好(`take`、`until`)。 |
|
|
239
|
+
| **同步与异步支持** | 统一的 API – 对两种范式都提供一等公民支持。 | 主要面向异步。 | 两者都支持,但需要手动桥接。 | 主要面向异步。 |
|
|
240
|
+
| **学习曲线** | 对于熟悉函数式和索引集合管道的开发者来说较平缓。 | 较陡峭(大量的操作符词汇、热/冷 Observable 概念)。 | 低到中等。 | 中等。 |
|
|
189
241
|
|
|
190
|
-
**Semantic
|
|
242
|
+
**Semantic‑TypeScript 的优势**
|
|
191
243
|
|
|
192
|
-
*
|
|
193
|
-
* 对事件流的显式控制,防止了 RxJS
|
|
194
|
-
*
|
|
244
|
+
* **独特能力:** 集成的统计和索引功能,无需手动 `reduce` 操作或辅助的数据分析库。
|
|
245
|
+
* **可预测的资源管理:** 对事件流的显式控制,防止了 RxJS 应用中可能出现的微妙内存泄漏。
|
|
246
|
+
* **统一设计:** 同步和异步工作流采用一致的 API,减少了认知负担和代码重复。
|
|
195
247
|
|
|
196
|
-
|
|
248
|
+
此对比凸显了为何 Semantic‑TypeScript 特别适合需要高性能、健壮的类型安全性和丰富数据处理功能,而又不希望引入传统响应式框架复杂性的现代 TypeScript 应用程序。
|
|
197
249
|
|
|
198
250
|
---
|
|
199
251
|
|
|
200
|
-
###
|
|
252
|
+
### 开始探索
|
|
253
|
+
|
|
254
|
+
Semantic‑TypeScript 将复杂的数据流转化为可读、可组合且高性能的管道。无论您是在处理实时 UI 事件、处理大量数据集,还是构建分析仪表板,它都能提供数据库级索引的强大功能与函数式编程的优雅。
|
|
201
255
|
|
|
202
|
-
|
|
256
|
+
**您的后续步骤:**
|
|
203
257
|
|
|
204
|
-
|
|
258
|
+
* 直接在您的 IDE 中探索完全类型化的 API(所有导出都可在主包入口点找到)。
|
|
259
|
+
* 加入不断壮大的开发者社区,他们已用清晰、有意的 Semantic 管道替代了复杂的异步迭代器和响应式链。
|
|
205
260
|
|
|
206
|
-
|
|
207
|
-
* 加入不断壮大的开发者社区,他们已用清晰的 Semantic 管道取代了复杂的异步迭代器。
|
|
261
|
+
**Semantic‑TypeScript** – 流与结构的交汇点。
|
|
208
262
|
|
|
209
|
-
|
|
263
|
+
立即开始构建,体验深思熟虑的索引设计所带来的切实差异。
|
|
210
264
|
|
|
211
|
-
|
|
265
|
+
**清晰构建,自信前行,以意图驱动数据转换。**
|
|
212
266
|
|
|
213
|
-
|
|
267
|
+
MIT © Eloy Kim
|