id-scanner-lib 1.3.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.
Files changed (101) hide show
  1. package/README.md +55 -460
  2. package/dist/id-scanner-lib.esm.js +4641 -0
  3. package/dist/id-scanner-lib.esm.js.map +1 -0
  4. package/dist/id-scanner-lib.js +14755 -0
  5. package/dist/id-scanner-lib.js.map +1 -0
  6. package/dist/types/core/base-module.d.ts +44 -0
  7. package/dist/types/core/camera-manager.d.ts +258 -0
  8. package/dist/types/core/config.d.ts +88 -0
  9. package/dist/types/core/errors.d.ts +111 -0
  10. package/dist/types/core/event-emitter.d.ts +55 -0
  11. package/dist/types/core/logger.d.ts +277 -0
  12. package/dist/types/core/module-manager.d.ts +78 -0
  13. package/dist/types/core/plugin-manager.d.ts +158 -0
  14. package/dist/types/core/resource-manager.d.ts +246 -0
  15. package/dist/types/core/result.d.ts +83 -0
  16. package/dist/types/core/scanner-factory.d.ts +93 -0
  17. package/dist/types/index.bundle.d.ts +1303 -0
  18. package/dist/types/index.d.ts +86 -0
  19. package/dist/types/interfaces/external-types.d.ts +174 -0
  20. package/dist/types/interfaces/face-detection.d.ts +293 -0
  21. package/dist/types/interfaces/scanner-module.d.ts +280 -0
  22. package/dist/types/modules/face/face-detector.d.ts +170 -0
  23. package/dist/types/modules/face/index.d.ts +56 -0
  24. package/dist/types/modules/face/liveness-detector.d.ts +177 -0
  25. package/dist/types/modules/face/types.d.ts +136 -0
  26. package/dist/types/modules/id-card/anti-fake-detector.d.ts +170 -0
  27. package/dist/types/modules/id-card/id-card-detector.d.ts +131 -0
  28. package/dist/types/modules/id-card/index.d.ts +89 -0
  29. package/dist/types/modules/id-card/ocr-processor.d.ts +110 -0
  30. package/dist/types/modules/id-card/ocr-worker.d.ts +31 -0
  31. package/dist/types/modules/id-card/types.d.ts +181 -0
  32. package/dist/types/modules/qrcode/index.d.ts +51 -0
  33. package/dist/types/modules/qrcode/qr-code-scanner.d.ts +64 -0
  34. package/dist/types/modules/qrcode/types.d.ts +67 -0
  35. package/dist/types/utils/camera.d.ts +81 -0
  36. package/dist/types/utils/image-processing.d.ts +176 -0
  37. package/dist/types/utils/index.d.ts +175 -0
  38. package/dist/types/utils/performance.d.ts +81 -0
  39. package/dist/types/utils/resource-manager.d.ts +53 -0
  40. package/dist/types/utils/types.d.ts +166 -0
  41. package/dist/types/utils/worker.d.ts +52 -0
  42. package/dist/types/version.d.ts +7 -0
  43. package/package.json +76 -75
  44. package/src/core/base-module.ts +78 -0
  45. package/src/core/camera-manager.ts +798 -0
  46. package/src/core/config.ts +268 -0
  47. package/src/core/errors.ts +174 -0
  48. package/src/core/event-emitter.ts +110 -0
  49. package/src/core/logger.ts +549 -0
  50. package/src/core/module-manager.ts +165 -0
  51. package/src/core/plugin-manager.ts +429 -0
  52. package/src/core/resource-manager.ts +762 -0
  53. package/src/core/result.ts +163 -0
  54. package/src/core/scanner-factory.ts +237 -0
  55. package/src/index.ts +113 -936
  56. package/src/interfaces/external-types.ts +200 -0
  57. package/src/interfaces/face-detection.ts +309 -0
  58. package/src/interfaces/scanner-module.ts +384 -0
  59. package/src/modules/face/face-detector.ts +931 -0
  60. package/src/modules/face/index.ts +208 -0
  61. package/src/modules/face/liveness-detector.ts +908 -0
  62. package/src/modules/face/types.ts +133 -0
  63. package/src/{id-recognition → modules/id-card}/anti-fake-detector.ts +273 -239
  64. package/src/modules/id-card/id-card-detector.ts +474 -0
  65. package/src/modules/id-card/index.ts +425 -0
  66. package/src/{id-recognition → modules/id-card}/ocr-processor.ts +149 -92
  67. package/src/modules/id-card/ocr-worker.ts +259 -0
  68. package/src/modules/id-card/types.ts +178 -0
  69. package/src/modules/qrcode/index.ts +175 -0
  70. package/src/modules/qrcode/qr-code-scanner.ts +230 -0
  71. package/src/modules/qrcode/types.ts +65 -0
  72. package/src/types/tesseract.d.ts +265 -22
  73. package/src/utils/image-processing.ts +68 -49
  74. package/src/utils/index.ts +426 -0
  75. package/src/utils/performance.ts +168 -131
  76. package/src/utils/resource-manager.ts +65 -146
  77. package/src/utils/types.ts +90 -2
  78. package/src/utils/worker.ts +123 -84
  79. package/src/version.ts +11 -0
  80. package/tools/scaffold.js +543 -0
  81. package/dist/id-scanner-core.esm.js +0 -11349
  82. package/dist/id-scanner-core.js +0 -11361
  83. package/dist/id-scanner-core.min.js +0 -1
  84. package/dist/id-scanner-ocr.esm.js +0 -2319
  85. package/dist/id-scanner-ocr.js +0 -2328
  86. package/dist/id-scanner-ocr.min.js +0 -1
  87. package/dist/id-scanner-qr.esm.js +0 -1296
  88. package/dist/id-scanner-qr.js +0 -1305
  89. package/dist/id-scanner-qr.min.js +0 -1
  90. package/dist/id-scanner.js +0 -4561
  91. package/dist/id-scanner.min.js +0 -1
  92. package/src/core.ts +0 -138
  93. package/src/demo/demo.ts +0 -204
  94. package/src/id-recognition/data-extractor.ts +0 -262
  95. package/src/id-recognition/id-detector.ts +0 -510
  96. package/src/id-recognition/ocr-worker.ts +0 -156
  97. package/src/index-umd.ts +0 -477
  98. package/src/ocr-module.ts +0 -187
  99. package/src/qr-module.ts +0 -179
  100. package/src/scanner/barcode-scanner.ts +0 -251
  101. package/src/scanner/qr-scanner.ts +0 -167
@@ -1,210 +1,247 @@
1
1
  /**
2
- * @file 性能优化工具类
3
- * @description 提供节流、防抖、缓存等性能优化功能
4
- * @module PerformanceUtils
2
+ * @file 性能优化工具
3
+ * @description 提供性能优化相关的工具函数
4
+ * @module utils/performance
5
5
  */
6
6
 
7
7
  /**
8
- * 节流函数:限制函数在一定时间内只能执行一次
9
- *
10
- * @param fn 需要节流的函数
11
- * @param delay 延迟时间(毫秒)
12
- * @returns 节流处理后的函数
13
- */
14
- export function throttle<T extends (...args: any[]) => any>(
15
- fn: T,
16
- delay: number
17
- ): (...args: Parameters<T>) => void {
18
- let lastCall = 0;
19
- let timeoutId: number | null = null;
20
-
21
- return function(this: any, ...args: Parameters<T>) {
22
- const now = Date.now();
23
- const remaining = delay - (now - lastCall);
24
-
25
- if (remaining <= 0) {
26
- if (timeoutId) {
27
- clearTimeout(timeoutId);
28
- timeoutId = null;
29
- }
30
- lastCall = now;
31
- fn.apply(this, args);
32
- } else if (!timeoutId) {
33
- timeoutId = window.setTimeout(() => {
34
- lastCall = Date.now();
35
- timeoutId = null;
36
- fn.apply(this, args);
37
- }, remaining);
38
- }
39
- };
40
- }
41
-
42
- /**
43
- * 防抖函数:函数在最后一次调用后延迟指定时间执行
44
- *
45
- * @param fn 需要防抖的函数
46
- * @param delay 延迟时间(毫秒)
47
- * @returns 防抖处理后的函数
48
- */
49
- export function debounce<T extends (...args: any[]) => any>(
50
- fn: T,
51
- delay: number
52
- ): (...args: Parameters<T>) => void {
53
- let timeoutId: number | null = null;
54
-
55
- return function(this: any, ...args: Parameters<T>) {
56
- if (timeoutId) {
57
- clearTimeout(timeoutId);
58
- }
59
-
60
- timeoutId = window.setTimeout(() => {
61
- fn.apply(this, args);
62
- timeoutId = null;
63
- }, delay);
64
- };
65
- }
66
-
67
- /**
68
- * LRU缓存类 - 使用最近最少使用策略的缓存实现
8
+ * LRU缓存实现
69
9
  */
70
10
  export class LRUCache<K, V> {
71
- private cache = new Map<K, V>();
72
-
11
+ private capacity: number;
12
+ private cache: Map<K, V>;
13
+
73
14
  /**
74
- * 构造LRU缓存
75
- * @param maxSize 缓存最大容量
15
+ * 构造函数
16
+ * @param capacity 缓存容量
76
17
  */
77
- constructor(private maxSize: number = 100) {}
78
-
18
+ constructor(capacity: number = 100) {
19
+ this.capacity = capacity;
20
+ this.cache = new Map<K, V>();
21
+ }
22
+
79
23
  /**
80
24
  * 获取缓存项
81
- * @param key 缓存键
82
- * @returns 缓存值或undefined
25
+ * @param key
26
+ * @returns 值,如果不存在则返回undefined
83
27
  */
84
28
  get(key: K): V | undefined {
85
29
  if (!this.cache.has(key)) {
86
30
  return undefined;
87
31
  }
88
-
32
+
89
33
  // 获取值
90
34
  const value = this.cache.get(key)!;
91
35
 
92
- // 将项移至最新位置(删除后重新添加)
36
+ // 删除旧位置
93
37
  this.cache.delete(key);
38
+
39
+ // 添加到最新位置
94
40
  this.cache.set(key, value);
95
-
41
+
96
42
  return value;
97
43
  }
98
-
44
+
99
45
  /**
100
46
  * 设置缓存项
101
- * @param key 缓存键
102
- * @param value 缓存值
47
+ * @param key
48
+ * @param value
103
49
  */
104
50
  set(key: K, value: V): void {
105
- // 如果键已存在,需要先删除
51
+ // 如果已存在,先删除
106
52
  if (this.cache.has(key)) {
107
53
  this.cache.delete(key);
108
54
  }
109
-
110
- // 如果缓存已满,移除最老的项
111
- if (this.cache.size >= this.maxSize) {
112
- const oldestKey = this.cache.keys().next().value;
113
- if (oldestKey !== undefined) {
114
- this.cache.delete(oldestKey);
115
- }
55
+ // 如果缓存已满,删除最旧的项
56
+ else if (this.cache.size >= this.capacity) {
57
+ this.cache.delete(this.cache.keys().next().value as K);
116
58
  }
117
-
59
+
118
60
  // 添加新项
119
61
  this.cache.set(key, value);
120
62
  }
121
63
 
64
+ /**
65
+ * 检查键是否存在
66
+ * @param key 键
67
+ * @returns 是否存在
68
+ */
69
+ has(key: K): boolean {
70
+ return this.cache.has(key);
71
+ }
72
+
122
73
  /**
123
74
  * 删除缓存项
124
- * @param key 缓存键
75
+ * @param key
125
76
  * @returns 是否成功删除
126
77
  */
127
78
  delete(key: K): boolean {
128
79
  return this.cache.delete(key);
129
80
  }
130
-
81
+
131
82
  /**
132
83
  * 清空缓存
133
84
  */
134
85
  clear(): void {
135
86
  this.cache.clear();
136
87
  }
137
-
88
+
138
89
  /**
139
- * 获取当前缓存大小
90
+ * 获取缓存大小
140
91
  */
141
92
  get size(): number {
142
93
  return this.cache.size;
143
94
  }
95
+
96
+ /**
97
+ * 获取所有键
98
+ */
99
+ keys(): IterableIterator<K> {
100
+ return this.cache.keys();
101
+ }
144
102
 
145
103
  /**
146
- * 检查键是否存在
147
- * @param key 缓存键
104
+ * 获取所有值
148
105
  */
149
- has(key: K): boolean {
150
- return this.cache.has(key);
106
+ values(): IterableIterator<V> {
107
+ return this.cache.values();
108
+ }
109
+
110
+ /**
111
+ * 获取所有项
112
+ */
113
+ entries(): IterableIterator<[K, V]> {
114
+ return this.cache.entries();
151
115
  }
152
116
  }
153
117
 
154
118
  /**
155
- * 图像指纹计算函数 - 用于检测相同或相似图像
156
- *
119
+ * 计算图像指纹
157
120
  * @param imageData 图像数据
158
- * @param size 指纹尺寸(默认8x8)
159
- * @returns 图像指纹字符串
121
+ * @returns 图像指纹
160
122
  */
161
- export function calculateImageFingerprint(imageData: ImageData, size: number = 8): string {
162
- // 1. 缩小图像到指定尺寸
123
+ export function calculateImageFingerprint(imageData: ImageData): string {
124
+ const { width, height, data } = imageData;
125
+
126
+ // 缩小图像以加快计算速度
127
+ const scale = Math.min(1, 32 / Math.max(width, height));
128
+ const scaledWidth = Math.max(8, Math.floor(width * scale));
129
+ const scaledHeight = Math.max(8, Math.floor(height * scale));
130
+
131
+ // 创建缩小的图像
163
132
  const canvas = document.createElement('canvas');
164
- canvas.width = size;
165
- canvas.height = size;
166
133
  const ctx = canvas.getContext('2d');
167
-
134
+
168
135
  if (!ctx) {
169
- return '';
136
+ throw new Error('无法创建Canvas上下文');
170
137
  }
171
138
 
172
- // 创建一个临时canvas来绘制原始imageData
139
+ // 设置canvas尺寸
140
+ canvas.width = scaledWidth;
141
+ canvas.height = scaledHeight;
142
+
143
+ // 创建临时canvas存储原始ImageData
173
144
  const tempCanvas = document.createElement('canvas');
174
- tempCanvas.width = imageData.width;
175
- tempCanvas.height = imageData.height;
176
145
  const tempCtx = tempCanvas.getContext('2d');
177
-
146
+
178
147
  if (!tempCtx) {
179
- return '';
148
+ throw new Error('无法创建临时Canvas上下文');
180
149
  }
181
-
150
+
151
+ tempCanvas.width = width;
152
+ tempCanvas.height = height;
182
153
  tempCtx.putImageData(imageData, 0, 0);
183
154
 
184
- // 缩小到目标尺寸
185
- ctx.drawImage(tempCanvas, 0, 0, imageData.width, imageData.height, 0, 0, size, size);
155
+ // 绘制缩小的图像
156
+ ctx.drawImage(tempCanvas, 0, 0, width, height, 0, 0, scaledWidth, scaledHeight);
186
157
 
187
- // 2. 转换为灰度
188
- const smallImgData = ctx.getImageData(0, 0, size, size);
189
- const grayValues = [];
158
+ // 获取缩小的图像数据
159
+ const scaledImageData = ctx.getImageData(0, 0, scaledWidth, scaledHeight);
190
160
 
191
- for (let i = 0; i < smallImgData.data.length; i += 4) {
192
- const r = smallImgData.data[i];
193
- const g = smallImgData.data[i + 1];
194
- const b = smallImgData.data[i + 2];
195
- // 转为灰度: 0.299r + 0.587g + 0.114b
196
- const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
197
- grayValues.push(gray);
161
+ // 计算灰度值
162
+ const grayValues = new Uint8Array(scaledWidth * scaledHeight);
163
+
164
+ for (let i = 0; i < scaledWidth * scaledHeight; i++) {
165
+ const idx = i * 4;
166
+ grayValues[i] = Math.round(
167
+ 0.299 * scaledImageData.data[idx] +
168
+ 0.587 * scaledImageData.data[idx + 1] +
169
+ 0.114 * scaledImageData.data[idx + 2]
170
+ );
198
171
  }
199
172
 
200
- // 3. 计算平均值
201
- const avg = grayValues.reduce((sum, val) => sum + val, 0) / grayValues.length;
173
+ // 计算平均值
174
+ let sum = 0;
175
+ for (let i = 0; i < grayValues.length; i++) {
176
+ sum += grayValues[i];
177
+ }
178
+ const avg = sum / grayValues.length;
202
179
 
203
- // 4. 比较每个像素与平均值,生成二进制指纹
204
- let fingerprint = '';
205
- for (const gray of grayValues) {
206
- fingerprint += gray >= avg ? '1' : '0';
180
+ // 计算哈希值
181
+ let hash = '';
182
+ for (let i = 0; i < grayValues.length; i++) {
183
+ hash += grayValues[i] >= avg ? '1' : '0';
207
184
  }
208
185
 
209
- return fingerprint;
210
- }
186
+ return hash;
187
+ }
188
+
189
+ /**
190
+ * 防抖函数
191
+ * @param func 要执行的函数
192
+ * @param wait 等待时间(毫秒)
193
+ * @returns 防抖处理后的函数
194
+ */
195
+ export function debounce<T extends (...args: any[]) => any>(
196
+ func: T,
197
+ wait: number
198
+ ): (...args: Parameters<T>) => void {
199
+ let timeout: number | null = null;
200
+
201
+ return function(this: any, ...args: Parameters<T>): void {
202
+ const later = () => {
203
+ timeout = null;
204
+ func.apply(this, args);
205
+ };
206
+
207
+ if (timeout !== null) {
208
+ clearTimeout(timeout);
209
+ }
210
+
211
+ timeout = window.setTimeout(later, wait) as unknown as number;
212
+ };
213
+ }
214
+
215
+ /**
216
+ * 节流函数
217
+ * @param func 要执行的函数
218
+ * @param limit 时间限制(毫秒)
219
+ * @returns 节流处理后的函数
220
+ */
221
+ export function throttle<T extends (...args: any[]) => any>(
222
+ func: T,
223
+ limit: number
224
+ ): (...args: Parameters<T>) => void {
225
+ let inThrottle = false;
226
+ let lastFunc: number | null = null;
227
+ let lastRan: number | null = null;
228
+
229
+ return function(this: any, ...args: Parameters<T>): void {
230
+ if (!inThrottle) {
231
+ func.apply(this, args);
232
+ lastRan = Date.now();
233
+ inThrottle = true;
234
+ } else {
235
+ if (lastFunc !== null) {
236
+ clearTimeout(lastFunc);
237
+ }
238
+
239
+ lastFunc = window.setTimeout(() => {
240
+ if (lastRan !== null && Date.now() - lastRan >= limit) {
241
+ func.apply(this, args);
242
+ lastRan = Date.now();
243
+ }
244
+ }, limit - (lastRan !== null ? Date.now() - lastRan : 0)) as unknown as number;
245
+ }
246
+ };
247
+ }
@@ -1,198 +1,117 @@
1
1
  /**
2
2
  * @file 资源管理器
3
- * @description 提供资源自动管理功能,防止内存泄漏
4
- * @module ResourceManager
3
+ * @description 提供资源管理和释放功能
4
+ * @module utils/resource-manager
5
5
  */
6
6
 
7
7
  /**
8
8
  * 可释放资源接口
9
9
  */
10
10
  export interface Disposable {
11
- dispose: () => void | Promise<void>;
11
+ /** 释放资源 */
12
+ dispose(): Promise<void> | void;
12
13
  }
13
14
 
14
15
  /**
15
- * 资源管理器
16
- *
17
- * 用于管理和自动释放资源,防止内存泄漏
16
+ * 资源管理器类
17
+ * 用于管理和自动释放资源
18
18
  */
19
19
  export class ResourceManager {
20
- private resources: Map<string, Disposable> = new Map();
21
- private disposeTimeouts: Map<string, number> = new Map();
22
- private autoDisposeDelay: number;
23
-
24
- /**
25
- * 创建资源管理器
26
- * @param autoDisposeDelay 自动释放延迟时间(毫秒),默认5分钟
27
- */
28
- constructor(autoDisposeDelay: number = 5 * 60 * 1000) {
29
- this.autoDisposeDelay = autoDisposeDelay;
30
-
31
- // 添加页面卸载事件监听,确保在页面关闭时释放所有资源
32
- if (typeof window !== 'undefined') {
33
- window.addEventListener('beforeunload', () => {
34
- this.disposeAll();
35
- });
36
- }
37
- }
20
+ private resources: Disposable[] = [];
38
21
 
39
22
  /**
40
23
  * 注册资源
41
- *
42
- * @param id 资源标识符
43
24
  * @param resource 可释放资源
44
- * @param autoDispose 是否自动释放
45
- * @returns 注册的资源
46
- */
47
- register<T extends Disposable>(id: string, resource: T, autoDispose: boolean = true): T {
48
- // 如果已存在同ID资源,先释放它
49
- if (this.resources.has(id)) {
50
- this.dispose(id);
51
- }
52
-
53
- this.resources.set(id, resource);
54
-
55
- // 如果启用自动释放,设置定时器
56
- if (autoDispose) {
57
- this.resetDisposeTimeout(id);
58
- }
59
-
60
- return resource;
61
- }
62
-
63
- /**
64
- * 重置资源自动释放定时器
65
- *
66
- * @param id 资源标识符
67
- */
68
- resetDisposeTimeout(id: string): void {
69
- // 取消现有定时器
70
- if (this.disposeTimeouts.has(id)) {
71
- window.clearTimeout(this.disposeTimeouts.get(id)!);
72
- }
73
-
74
- // 设置新定时器
75
- const timeoutId = window.setTimeout(() => {
76
- this.dispose(id);
77
- }, this.autoDisposeDelay);
78
-
79
- this.disposeTimeouts.set(id, timeoutId);
80
- }
81
-
82
- /**
83
- * 获取资源
84
- *
85
- * @param id 资源标识符
86
- * @returns 资源对象或undefined
25
+ * @returns 资源本身,便于链式调用
87
26
  */
88
- get<T extends Disposable>(id: string): T | undefined {
89
- const resource = this.resources.get(id) as T | undefined;
90
-
91
- // 重置自动释放定时器(仅当资源存在且有定时器时)
92
- if (resource && this.disposeTimeouts.has(id)) {
93
- this.resetDisposeTimeout(id);
94
- }
95
-
27
+ register<T extends Disposable>(resource: T): T {
28
+ this.resources.push(resource);
96
29
  return resource;
97
30
  }
98
31
 
99
32
  /**
100
- * 释放单个资源
101
- *
102
- * @param id 资源标识符
33
+ * 释放指定资源
34
+ * @param resource 要释放的资源
103
35
  * @returns 是否成功释放
104
36
  */
105
- async dispose(id: string): Promise<boolean> {
106
- if (!this.resources.has(id)) {
107
- return false;
108
- }
109
-
110
- // 取消定时器
111
- if (this.disposeTimeouts.has(id)) {
112
- window.clearTimeout(this.disposeTimeouts.get(id)!);
113
- this.disposeTimeouts.delete(id);
114
- }
115
-
116
- // 释放资源
117
- try {
118
- const resource = this.resources.get(id)!;
119
- const result = resource.dispose();
120
-
121
- // 处理可能的Promise结果
122
- if (result instanceof Promise) {
123
- await result;
124
- }
125
-
126
- this.resources.delete(id);
37
+ async release(resource: Disposable): Promise<boolean> {
38
+ const index = this.resources.indexOf(resource);
39
+ if (index !== -1) {
40
+ try {
41
+ await resource.dispose();
42
+ this.resources.splice(index, 1);
127
43
  return true;
128
44
  } catch (error) {
129
- console.error(`释放资源 ${id} 时发生错误:`, error);
130
- // 尽管出错,仍然从管理器中移除
131
- this.resources.delete(id);
45
+ console.error('释放资源失败:', error);
132
46
  return false;
47
+ }
133
48
  }
49
+ return false;
134
50
  }
135
51
 
136
52
  /**
137
53
  * 释放所有资源
138
54
  */
139
- async disposeAll(): Promise<void> {
140
- // 取消所有定时器
141
- for (const timeoutId of this.disposeTimeouts.values()) {
142
- window.clearTimeout(timeoutId);
143
- }
144
- this.disposeTimeouts.clear();
145
-
146
- // 并行释放所有资源
147
- const disposePromises = [];
55
+ async releaseAll(): Promise<void> {
56
+ const promises: Promise<void>[] = [];
148
57
 
149
- for (const [id, resource] of this.resources.entries()) {
58
+ for (const resource of this.resources) {
150
59
  try {
151
60
  const result = resource.dispose();
152
61
  if (result instanceof Promise) {
153
- disposePromises.push(result);
62
+ promises.push(result);
154
63
  }
155
64
  } catch (error) {
156
- console.error(`释放资源 ${id} 时发生错误:`, error);
65
+ console.error('释放资源失败:', error);
157
66
  }
158
67
  }
159
68
 
160
- // 等待所有异步释放完成
161
- if (disposePromises.length > 0) {
162
- await Promise.all(disposePromises);
163
- }
164
-
165
- this.resources.clear();
69
+ await Promise.all(promises);
70
+ this.resources = [];
166
71
  }
167
72
 
168
73
  /**
169
- * 释放不活跃资源
170
- *
171
- * @param maxAge 资源最大年龄(毫秒)
74
+ * 获取当前管理的资源数量
172
75
  */
173
- disposeInactive(maxAge: number): void {
174
- const now = Date.now();
175
-
176
- for (const [id, timeoutId] of this.disposeTimeouts.entries()) {
177
- // 计算资源年龄:自动释放延迟时间 - 剩余时间
178
- const remainingTime = this.getRemainingTime(timeoutId);
179
- const age = this.autoDisposeDelay - remainingTime;
180
-
181
- if (age > maxAge) {
182
- this.dispose(id);
183
- }
76
+ get count(): number {
77
+ return this.resources.length;
184
78
  }
185
79
  }
186
80
 
187
81
  /**
188
- * 获取定时器剩余时间
189
- *
190
- * @param timeoutId 定时器ID
191
- * @returns 剩余时间(毫秒)
192
- */
193
- private getRemainingTime(timeoutId: number): number {
194
- // 注意:这是一个近似实现,因为JavaScript没有提供获取setTimeout剩余时间的API
195
- // 可以在实际应用中使用更精确的测量方法
196
- return 0; // 实际应用中应返回真实的剩余时间
82
+ * 创建一个自动释放的资源
83
+ * @param factory 资源工厂函数
84
+ * @param disposeCallback 释放回调函数
85
+ * @returns 创建的资源
86
+ */
87
+ export function createDisposable<T>(
88
+ factory: () => T,
89
+ disposeCallback: (resource: T) => Promise<void> | void
90
+ ): T & Disposable {
91
+ const resource = factory();
92
+
93
+ // 添加dispose方法
94
+ (resource as any).dispose = async () => {
95
+ await disposeCallback(resource);
96
+ };
97
+
98
+ return resource as T & Disposable;
99
+ }
100
+
101
+ /**
102
+ * 使用资源并自动释放
103
+ * @param resource 可释放资源
104
+ * @param callback 使用资源的回调函数
105
+ * @returns 回调函数的返回值
106
+ */
107
+ export async function using<T extends Disposable, R>(
108
+ resource: T,
109
+ callback: (resource: T) => Promise<R> | R
110
+ ): Promise<R> {
111
+ try {
112
+ const result = await callback(resource);
113
+ return result;
114
+ } finally {
115
+ await resource.dispose();
197
116
  }
198
117
  }