nhanh-pure-function 1.3.20 → 1.3.22

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.
@@ -226,28 +226,50 @@ export function _GetHrefName(href, defaultName = "file") {
226
226
  * @param {string} href - 文件路径
227
227
  * @param {string} [fileName] - 导出文件名
228
228
  */
229
- export async function _DownloadFile(href, fileName) {
230
- try {
231
- const response = await fetch(href); // 获取文件
232
- if (!response.ok) throw new Error("文件下载失败");
233
-
234
- const blob = await response.blob(); // 将响应转换为 Blob 对象
235
- const url = URL.createObjectURL(blob); // 创建文件 URL
236
-
237
- const a = document.createElement("a");
238
- a.href = url;
239
- a.download = fileName || _GetHrefName(href, "image");
240
-
241
- // 临时将 a 标签添加到 DOM,然后触发点击事件,最后移除
242
- document.body.appendChild(a);
243
- a.click();
244
- document.body.removeChild(a);
245
-
246
- // 释放 URL 对象
247
- URL.revokeObjectURL(url);
248
- } catch (error) {
249
- console.error("下载文件时发生错误:", error);
250
- }
229
+ export function _DownloadFile(href, fileName) {
230
+ return new Promise((resolve, reject) => {
231
+ _CheckConnectionWithXHR(href)
232
+ .then(() => {
233
+ try {
234
+ if (typeof fileName !== "string") {
235
+ fileName = _GetHrefName(href, "downloaded_file");
236
+ }
237
+
238
+ fetch(href)
239
+ .then((response) => {
240
+ if (!response.ok) {
241
+ throw new Error(`文件下载失败,状态码: ${response.status}`);
242
+ }
243
+ return response.blob();
244
+ })
245
+ .then((blob) => {
246
+ const url = URL.createObjectURL(blob); // 创建文件 URL
247
+
248
+ const a = document.createElement("a");
249
+ a.href = url;
250
+ a.download = decodeURIComponent(fileName);
251
+
252
+ // 临时将 a 标签添加到 DOM,然后触发点击事件,最后移除
253
+ document.body.appendChild(a);
254
+ a.click();
255
+ document.body.removeChild(a);
256
+
257
+ // 释放 URL 对象
258
+ URL.revokeObjectURL(url);
259
+
260
+ resolve();
261
+ })
262
+ .catch((error) => {
263
+ console.error("下载文件时发生错误:", error.message);
264
+ reject(error);
265
+ });
266
+ } catch (error) {
267
+ console.error("下载文件时发生错误:", error.message);
268
+ reject(error);
269
+ }
270
+ })
271
+ .catch(reject);
272
+ });
251
273
  }
252
274
 
253
275
  /**
@@ -384,13 +406,17 @@ export function _Debounce(fn, delay) {
384
406
  * @returns {Function}
385
407
  */
386
408
  export function _Throttle(fn, delay) {
387
- let timer;
409
+ let lastCallTime = -Infinity;
410
+
388
411
  return function (...args) {
389
- if (!timer) {
390
- timer = setTimeout(() => {
391
- fn.apply(this, args);
392
- timer = null;
393
- }, delay);
412
+ const now = performance.now();
413
+ if (now - lastCallTime > delay) {
414
+ lastCallTime = now;
415
+ try {
416
+ fn(...args);
417
+ } catch (error) {
418
+ console.error("Throttled function execution failed:", error);
419
+ }
394
420
  }
395
421
  };
396
422
  }
@@ -556,16 +582,52 @@ export function _UpdateTargetByPath(model, path, value) {
556
582
  */
557
583
  export function _CheckConnectionWithXHR(url) {
558
584
  return new Promise((resolve, reject) => {
585
+ // 前置校验:确保 URL 合法
586
+ if (typeof url !== "string" || url.trim() === "" || !url.includes("://")) {
587
+ reject(new Error("Invalid URL: Must be a non-empty string"));
588
+ return;
589
+ }
590
+
591
+ // 显式处理浏览器兼容性错误(如无效协议或非法字符)
592
+ try {
593
+ const xhr = new XMLHttpRequest();
594
+ xhr.open("HEAD", url, true);
595
+ } catch (error) {
596
+ reject(new Error(`Invalid URL format: ${error.message}`));
597
+ return;
598
+ }
599
+
559
600
  const xhr = new XMLHttpRequest();
560
- xhr.open("HEAD", url, true); // 发送 HEAD 请求
601
+ xhr.open("HEAD", url, true);
602
+
603
+ // 统一错误处理逻辑
604
+ const handleError = (event) => {
605
+ reject(new Error(`Request failed: ${event.type}`));
606
+ };
607
+
561
608
  xhr.onreadystatechange = function () {
562
609
  if (xhr.readyState === XMLHttpRequest.DONE) {
563
- if (xhr.status >= 200 && xhr.status < 300) resolve();
564
- else reject(xhr);
610
+ // 兼容性处理:status=0 可能是跨域或网络错误
611
+ if (xhr.status === 0) {
612
+ reject(new Error("Network error or CORS blocked"));
613
+ } else if (xhr.status >= 200 && xhr.status < 300) {
614
+ resolve();
615
+ } else {
616
+ reject(new Error(`HTTP Error: ${xhr.status}`));
617
+ }
565
618
  }
566
619
  };
567
- xhr.onerror = reject;
568
- xhr.send();
620
+
621
+ // 绑定所有可能的错误事件
622
+ xhr.onerror = handleError; // 网络层错误(如 DNS 解析失败)
623
+ xhr.onabort = handleError; // 请求被中止
624
+ xhr.ontimeout = handleError; // 超时
625
+
626
+ try {
627
+ xhr.send();
628
+ } catch (error) {
629
+ reject(new Error(`Request send failed: ${error.message}`));
630
+ }
569
631
  });
570
632
  }
571
633
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nhanh-pure-function",
3
- "version": "1.3.20",
3
+ "version": "1.3.22",
4
4
  "description": "纯函数工具",
5
5
  "main": "lib/Index.js",
6
6
  "scripts": {