id-scanner-lib 1.6.4 → 1.6.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "id-scanner-lib",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "Browser-based ID card, QR code, and face recognition scanner with liveness detection",
5
5
  "main": "dist/id-scanner-lib.js",
6
6
  "module": "dist/id-scanner-lib.esm.js",
@@ -219,18 +219,25 @@ export class RemoteLogHandler implements LogHandler {
219
219
  'Content-Type': 'application/json'
220
220
  },
221
221
  body: JSON.stringify(entriesToSend),
222
- // 不等待响应,避免阻塞
223
222
  keepalive: true
224
223
  }).catch((err: Error) => {
225
224
  console.error('Failed to send logs to remote server:', err);
225
+
226
+ // 防止无限重试 - 如果失败次数过多,丢弃日志
227
+ if ((this as any)._sendCount > 10) {
228
+ console.warn('RemoteLogHandler: Max retry exceeded, discarding logs');
229
+ this.queue = []; // 清空队列,避免内存泄漏
230
+ (this as any)._sendCount = 0;
231
+ return;
232
+ }
233
+
226
234
  // 失败时把日志放回队列,但防止无限增长
227
235
  if (this.queue.length < this.maxQueueSize) {
228
- // 限制放回的数量,防止内存溢出
229
236
  const maxReturn = Math.min(entriesToSend.length, this.maxQueueSize - this.queue.length);
230
237
  const returnedEntries = entriesToSend.slice(0, maxReturn);
231
238
  this.queue = [...returnedEntries, ...this.queue];
232
239
  }
233
- // 重置发送计数,允许后续重试
240
+
234
241
  (this as any)._sendCount = 0;
235
242
  });
236
243
  } catch (error) {
@@ -140,7 +140,7 @@ export class OCRProcessor implements Disposable {
140
140
  * @param imageData 要处理的身份证图像数据
141
141
  * @returns 提取的身份证信息
142
142
  */
143
- async processIDCard(imageData: ImageData): Promise<IDCardInfo> {
143
+ async processIDCard(imageData: ImageData): Promise<IDCardInfo | null> {
144
144
  if (!this.initialized) {
145
145
  await this.initialize()
146
146
  }
@@ -249,8 +249,8 @@ export class OCRProcessor implements Disposable {
249
249
 
250
250
  this.options.logger?.(`OCR识别错误: ${errorMessage}`);
251
251
 
252
- // 返回空对象,避免完全失败
253
- return {} as IDCardInfo
252
+ // 返回 null,让调用方知道识别失败
253
+ return null;
254
254
  }
255
255
  }
256
256
 
@@ -105,15 +105,28 @@ export class Camera {
105
105
  // 绑定到视频元素
106
106
  if (this.videoElement) {
107
107
  this.videoElement.srcObject = this.stream;
108
- await new Promise<void>((resolve) => {
108
+
109
+ // 添加超时保护,防止永久挂起
110
+ const timeoutPromise = new Promise<never>((_, reject) => {
111
+ setTimeout(() => reject(new Error('摄像头初始化超时')), 10000); // 10秒超时
112
+ });
113
+
114
+ const playPromise = new Promise<void>((resolve, reject) => {
109
115
  if (this.videoElement) {
110
116
  this.videoElement.onloadedmetadata = () => {
111
117
  if (this.videoElement) {
112
- this.videoElement.play().then(() => resolve());
118
+ this.videoElement.play()
119
+ .then(() => resolve())
120
+ .catch(err => reject(err));
113
121
  }
114
122
  };
123
+ this.videoElement.onerror = () => reject(new Error('视频加载失败'));
124
+ } else {
125
+ reject(new Error('视频元素未初始化'));
115
126
  }
116
127
  });
128
+
129
+ await Promise.race([playPromise, timeoutPromise]);
117
130
  }
118
131
  } catch (error) {
119
132
  const logger = Logger.getInstance();