@zwa73/utils 1.0.80 → 1.0.81

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 (44) hide show
  1. package/{test/test.js → backup/repeatPromise.test.ts} +0 -1
  2. package/compile.bat +2 -0
  3. package/dist/QuickFunction.d.ts +2 -15
  4. package/dist/QuickFunction.js +21 -19
  5. package/dist/UtilCodecs.js +1 -1
  6. package/dist/UtilCom.js +1 -1
  7. package/dist/UtilDecorators.d.ts +1 -1
  8. package/dist/UtilDecorators.js +4 -3
  9. package/dist/UtilFP.js +1 -1
  10. package/dist/UtilFileTools.js +1 -1
  11. package/dist/UtilFunctions.d.ts +65 -18
  12. package/dist/UtilFunctions.js +141 -29
  13. package/dist/UtilInterfaces.d.ts +18 -13
  14. package/dist/UtilSymbol.d.ts +29 -10
  15. package/dist/UtilSymbol.js +22 -9
  16. package/dist/test/test.js +16 -16
  17. package/jest/UtilFunction/queueProc.test.ts +23 -0
  18. package/jest/UtilFunction/repeatPromise.test.ts +38 -0
  19. package/jest/jest.test.ts +46 -0
  20. package/jest.config.js +16 -0
  21. package/package.json +12 -5
  22. package/release.bat +3 -4
  23. package/{postinstall.js → scripts/postinstall.js} +2 -2
  24. package/src/QuickFunction.ts +47 -28
  25. package/src/UtilDecorators.ts +3 -1
  26. package/src/UtilFunctions.ts +183 -44
  27. package/src/UtilInterfaces.ts +44 -11
  28. package/src/UtilSymbol.ts +35 -11
  29. package/src/test/repeatTest.ts +1 -1
  30. package/test.bat +1 -1
  31. package/tsconfig.compile.json +4 -0
  32. package/tsconfig.json +3 -2
  33. package/watch.bat +1 -0
  34. package/test/test.bat +0 -2
  35. package/testAndCompile.bat +0 -4
  36. package/tsCompile.bat +0 -3
  37. package/tsCompileWatch.bat +0 -2
  38. /package/{test.js → backup/SLogger.test.ts} +0 -0
  39. /package/{req_test → backup/req_test}/cjsRmjs.bat +0 -0
  40. /package/{req_test → backup/req_test}/cjsRmjs.cjs +0 -0
  41. /package/{req_test → backup/req_test}/mjsRcjs.bat +0 -0
  42. /package/{req_test → backup/req_test}/mjsRcjs.mjs +0 -0
  43. /package/{req_test → backup/req_test}/req.cjs +0 -0
  44. /package/{req_test → backup/req_test}/req.mjs +0 -0
package/dist/test/test.js CHANGED
@@ -33,25 +33,25 @@ om.monfunc1(); //?
33
33
  om.m1num; //?
34
34
  const BASE_MAX = { 攻击: 24, 生命: 54, 防御: 16, 暴击: 5, 暴击伤害: 5, 攻击加成: 3.8, 生命加成: 3.8, 防御加成: 3.8 };
35
35
  const 精调前 = [
36
- { 攻击: 17, 生命: 0, 防御: 0, 暴击: 0, 暴击伤害: 3.5, 攻击加成: 3.0, 生命加成: 0, 防御加成: 3.4 },
37
- { 攻击: 19, 生命: 0, 防御: 0, 暴击: 4.5, 暴击伤害: 4.5, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 },
38
- { 攻击: 21, 生命: 0, 防御: 10, 暴击: 0, 暴击伤害: 0, 攻击加成: 3.8, 生命加成: 0, 防御加成: 3.0 },
39
- { 攻击: 17, 生命: 48, 防御: 14, 暴击: 0, 暴击伤害: 0, 攻击加成: 2.6, 生命加成: 0, 防御加成: 0 },
40
- { 攻击: 23, 生命: 0, 防御: 0, 暴击: 5, 暴击伤害: 0, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 },
41
- { 攻击: 17, 生命: 53, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 },
42
- { 攻击: 21, 生命: 0, 防御: 0, 暴击: 3.5, 暴击伤害: 0, 攻击加成: 3.0, 生命加成: 0, 防御加成: 0 },
43
- { 攻击: 17, 生命: 0, 防御: 3.8, 暴击: 0, 暴击伤害: 0, 攻击加成: 2.6, 生命加成: 0, 防御加成: 0 },
36
+ { 攻击: 17, 生命: 0, 防御: 0, 暴击: 0, 暴击伤害: 3.5, 攻击加成: 3.0, 生命加成: 0, 防御加成: 3.4 }, // 霰弹 专用消焰器
37
+ { 攻击: 19, 生命: 0, 防御: 0, 暴击: 4.5, 暴击伤害: 4.5, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 }, // 霰弹 专用消音器
38
+ { 攻击: 21, 生命: 0, 防御: 10, 暴击: 0, 暴击伤害: 0, 攻击加成: 3.8, 生命加成: 0, 防御加成: 3.0 }, // 机枪 重型制退器
39
+ { 攻击: 17, 生命: 48, 防御: 14, 暴击: 0, 暴击伤害: 0, 攻击加成: 2.6, 生命加成: 0, 防御加成: 0 }, // 冲锋 消焰器攻击头
40
+ { 攻击: 23, 生命: 0, 防御: 0, 暴击: 5, 暴击伤害: 0, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 }, // 狙击 异位打击 快拆战术手电
41
+ { 攻击: 17, 生命: 53, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 }, // 霰弹 减伤支援 钢化铆钉
42
+ { 攻击: 21, 生命: 0, 防御: 0, 暴击: 3.5, 暴击伤害: 0, 攻击加成: 3.0, 生命加成: 0, 防御加成: 0 }, // 冲锋 异位打击 内瞄式红点
43
+ { 攻击: 17, 生命: 0, 防御: 3.8, 暴击: 0, 暴击伤害: 0, 攻击加成: 2.6, 生命加成: 0, 防御加成: 0 }, // 机枪 双重对策 镭射插件
44
44
  { 攻击: 19, 生命: 38, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 3.4, 生命加成: 0, 防御加成: 0 }, // 机枪 双重对策 折叠脚架
45
45
  ];
46
46
  const 精调后 = [
47
- { 攻击: 26, 生命: 0, 防御: 0, 暴击: 0, 暴击伤害: 8.1, 攻击加成: 7.5, 生命加成: 0, 防御加成: 5.8 },
48
- { 攻击: 31, 生命: 0, 防御: 0, 暴击: 10.4, 暴击伤害: 10.4, 攻击加成: 7.5, 生命加成: 0, 防御加成: 0 },
49
- { 攻击: 49, 生命: 0, 防御: 17, 暴击: 0, 暴击伤害: 0, 攻击加成: 7.6, 生命加成: 0, 防御加成: 6.9 },
50
- { 攻击: 46, 生命: 116, 防御: 27, 暴击: 0, 暴击伤害: 0, 攻击加成: 5.0, 生命加成: 0, 防御加成: 0 },
51
- { 攻击: 42, 生命: 0, 防御: 0, 暴击: 11.5, 暴击伤害: 0, 攻击加成: 6.8, 生命加成: 0, 防御加成: 0 },
52
- { 攻击: 34, 生命: 101, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 6.5, 生命加成: 0, 防御加成: 0 },
53
- { 攻击: 38, 生命: 0, 防御: 0, 暴击: 8.4, 暴击伤害: 0, 攻击加成: 4.8, 生命加成: 0, 防御加成: 0 },
54
- { 攻击: 43, 生命: 0, 防御: 8.0, 暴击: 0, 暴击伤害: 0, 攻击加成: 7.3, 生命加成: 0, 防御加成: 0 },
47
+ { 攻击: 26, 生命: 0, 防御: 0, 暴击: 0, 暴击伤害: 8.1, 攻击加成: 7.5, 生命加成: 0, 防御加成: 5.8 }, // 霰弹 专用消焰器
48
+ { 攻击: 31, 生命: 0, 防御: 0, 暴击: 10.4, 暴击伤害: 10.4, 攻击加成: 7.5, 生命加成: 0, 防御加成: 0 }, // 霰弹 专用消音器
49
+ { 攻击: 49, 生命: 0, 防御: 17, 暴击: 0, 暴击伤害: 0, 攻击加成: 7.6, 生命加成: 0, 防御加成: 6.9 }, // 机枪 重型制退器
50
+ { 攻击: 46, 生命: 116, 防御: 27, 暴击: 0, 暴击伤害: 0, 攻击加成: 5.0, 生命加成: 0, 防御加成: 0 }, // 冲锋 消焰器攻击头
51
+ { 攻击: 42, 生命: 0, 防御: 0, 暴击: 11.5, 暴击伤害: 0, 攻击加成: 6.8, 生命加成: 0, 防御加成: 0 }, // 狙击 异位打击 快拆战术
52
+ { 攻击: 34, 生命: 101, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 6.5, 生命加成: 0, 防御加成: 0 }, // 霰弹 减伤支援 钢化铆钉
53
+ { 攻击: 38, 生命: 0, 防御: 0, 暴击: 8.4, 暴击伤害: 0, 攻击加成: 4.8, 生命加成: 0, 防御加成: 0 }, // 冲锋 异位打击 内瞄式红
54
+ { 攻击: 43, 生命: 0, 防御: 8.0, 暴击: 0, 暴击伤害: 0, 攻击加成: 7.3, 生命加成: 0, 防御加成: 0 }, // 机枪 双重对策 镭射插件
55
55
  { 攻击: 42, 生命: 54, 防御: 0, 暴击: 0, 暴击伤害: 0, 攻击加成: 6.2, 生命加成: 0, 防御加成: 0 }, // 机枪 双重对策 折叠脚架
56
56
  ];
57
57
  const Pointify = (ed) => UtilFunctions_1.UtilFunc.mapEntries(ed, (k, v) => v ? v / BASE_MAX[k] : 0);
@@ -0,0 +1,23 @@
1
+ import { UtilFunc } from '@';
2
+ import { test, expect } from '@jest/globals';
3
+
4
+ test('queueProc function', async () => {
5
+ const results:number[] = [];
6
+ const expectedResults:number[] = [];
7
+ const tasks = Array.from({length: 10}, (_, i) => {
8
+ const result = Math.floor(Math.random() * 100); // 随机生成结果
9
+ expectedResults.push(result);
10
+ return async () => {
11
+ await UtilFunc.sleep(Math.random() * 800); // 随机延迟
12
+ results.push(result);
13
+ };
14
+ });
15
+ console.log("结果应该为:",expectedResults);
16
+
17
+ // 同时启动所有任务,但由于 queueProc 的设计,它们应该按顺序完成
18
+ const promises = tasks.map(task => UtilFunc.queueProc('test', task));
19
+ await Promise.all(promises);
20
+
21
+ // 检查结果是否按顺序
22
+ expect(results).toEqual(expectedResults);
23
+ },10000);
@@ -0,0 +1,38 @@
1
+ import { Completed, Failed, PromiseStat, PromiseVerifyFn, Success, UtilFunc } from "@";
2
+ import { test, expect } from '@jest/globals';
3
+
4
+
5
+
6
+
7
+ const timeList = [8000,1000,1000000] as const;
8
+ const resList = [Success,Failed,Failed] as const;
9
+ let index = 0;
10
+
11
+ // 模拟的异步函数,有一定几率失败
12
+ async function mockAsyncFunction() {
13
+ return new Promise<Success|Failed>((resolve, reject) => {
14
+ let delay = timeList[index];
15
+ let result = resList[index];
16
+ console.log('当前预期 延迟:',delay,' 结果:',result);
17
+ setTimeout(() => {
18
+ resolve(result);
19
+ }, delay);
20
+ index++;
21
+ });
22
+ }
23
+
24
+ // 验证函数,只有当结果为 "Success" 时才认为成功
25
+ function mockVerifyFunction(result:Success|Failed):PromiseStat {
26
+ return result === Success ? Success : Failed;
27
+ }
28
+
29
+ // 测试 repeatPromise 函数
30
+ test('repeatPromise', async () => {
31
+ const repeatCount = 3;
32
+ const awaitTime = 5;
33
+ console.log("重试次数:",repeatCount," 超时时间:",awaitTime)
34
+ const result = await UtilFunc.repeatPromise(
35
+ mockAsyncFunction, mockVerifyFunction,
36
+ repeatCount, awaitTime);
37
+ expect(result).toBe(Success);
38
+ },10000);
@@ -0,0 +1,46 @@
1
+ import { test, expect } from '@jest/globals';
2
+ // main.test.ts
3
+ const add = (a: number, b: number): number => a + b;
4
+
5
+ test('1+2等于3', () => {
6
+ expect(add(1, 2)).toBe(3);
7
+ });
8
+ test('console.log test', () => {
9
+ const consoleSpy = jest.spyOn(console, 'log');
10
+
11
+ // 这里是你的函数,它会打印 "成功" 或 "失败"
12
+ function yourFunction() {
13
+ console.log('成功');
14
+ }
15
+
16
+ yourFunction();
17
+
18
+ expect(consoleSpy).toHaveBeenCalledWith('成功');
19
+
20
+ // 清理 spy
21
+ consoleSpy.mockRestore();
22
+ });
23
+
24
+ test('mult console.log test', () => {
25
+ const consoleSpy = jest.spyOn(console, 'log');
26
+
27
+ // 这里是你的函数
28
+ function yourFunction() {
29
+ console.log("xxxx1234");
30
+ console.log("111abc22");
31
+ console.log("11def");
32
+ console.log("xxxxxxx");
33
+ }
34
+
35
+ yourFunction();
36
+
37
+ // 检查 console.log 的输出中是否包含 "abc" 和 "def"
38
+ const hasAbc = consoleSpy.mock.calls.some(args => args.some(arg => arg.includes('abc')));
39
+ const hasDef = consoleSpy.mock.calls.some(args => args.some(arg => arg.includes('def')));
40
+
41
+ expect(hasAbc).toBe(true);
42
+ expect(hasDef).toBe(true);
43
+
44
+ // 清理 spy
45
+ consoleSpy.mockRestore();
46
+ });
package/jest.config.js ADDED
@@ -0,0 +1,16 @@
1
+
2
+
3
+
4
+
5
+ module.exports = {
6
+ roots: ['./jest'],
7
+ transform: {
8
+ '^.+\\.tsx?$': 'ts-jest',
9
+ },
10
+ moduleNameMapper: {
11
+ '^@src/(.*)$': '<rootDir>/dist/$1',
12
+ '^@/(.*)$': '<rootDir>/$1',
13
+ '^@$': '<rootDir>/index'
14
+ },
15
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
16
+ };
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@zwa73/utils",
3
- "version": "1.0.80",
3
+ "version": "1.0.81",
4
4
  "description": "my utils",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node test",
8
- "postinstall": "start node postinstall.js",
9
- "release": "call release.bat"
7
+ "test": "call npm run compile && jest",
8
+ "postinstall": "start node ./scripts/postinstall.js",
9
+ "release": "call release.bat",
10
+ "compile": "call tsc -p tsconfig.compile.json && call tsc-alias -p tsconfig.compile.json",
11
+ "watch": "start tsc-alias -w -p tsconfig.compile.json && start tsc -w -p tsconfig.compile.json"
10
12
  },
11
13
  "keywords": [
12
14
  "zwa73"
@@ -28,6 +30,11 @@
28
30
  "winston-daily-rotate-file": "^4.7.1"
29
31
  },
30
32
  "devDependencies": {
31
- "@types/node": "^18.16.3"
33
+ "@types/jest": "^29.5.12",
34
+ "@types/node": "^18.16.3",
35
+ "jest": "^29.7.0",
36
+ "ts-jest": "^29.1.2",
37
+ "tsc-alias": "^1.8.8",
38
+ "typescript": "^5.3.3"
32
39
  }
33
40
  }
package/release.bat CHANGED
@@ -1,5 +1,4 @@
1
- call tsc
2
- call tsc-alias
3
- node build.js
4
- npm publish --access public
1
+ call npm run compile
2
+ call node build.js
3
+ call npm publish --access public
5
4
  pause
@@ -1,6 +1,6 @@
1
- const currentVersion = require('./package.json').version;
1
+ const currentVersion = require('../package.json').version;
2
2
  const path = require('path');
3
- const { UtilFT } = require("./index");
3
+ const { UtilFT } = require("../index");
4
4
  const readline = require('readline');
5
5
 
6
6
  // 将版本号转换为可以比较的数字
@@ -1,37 +1,56 @@
1
- import { ExtractOutcome, Keyable, Outcome, UnionToIntersection } from "./UtilInterfaces";
2
-
3
- /**创建一个Outcome */
4
- export function outcome<K extends Keyable,V> (key:K,value:V):Outcome<K,V>{
5
- return {status:key,result:value}
6
- }
1
+ import { UtilFunc } from "./UtilFunctions";
2
+ import { Outcome } from "./UtilInterfaces";
3
+ import { Completed, Failed, FailedLike, None, NoneOut, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
7
4
 
5
+ export const {
6
+ outcome,
7
+ matchProc,
8
+ sucesProc,
9
+ isFailed,
10
+ isSafeNumber,
11
+ isSuccess,
12
+ assertType,
13
+ assertLiteral,
14
+ deepClone,
15
+ sleep,
16
+ stringifyJToken,
17
+ getTime,
18
+ mapEntries,
19
+ composeMixinable
20
+ } = UtilFunc;
8
21
 
9
- /**处理联合值
10
- * @param t - 目标值
11
- * @param procObj - 所有可能的id组成的处理函数映射
12
- * @returns 任意处理函数的返回值
13
- */
14
- export function match<
15
- T extends Keyable | Outcome<Keyable, unknown>,
16
- P extends UnionToIntersection<(T extends Keyable
17
- ? {[K in T]:(k:K)=>unknown}
18
- : T extends Outcome<Keyable,unknown>
19
- ? { [K in T['status']] : (k:K,v:ExtractOutcome<T,K>['result'])=>unknown }
20
- : never)>>
21
- (t:T, procObj:P):
22
- P extends Record<any,(...args:any)=>any>
23
- ? {[K in keyof P]: ReturnType<P[K]>}[keyof P]
24
- : never {
25
- if (typeof t === 'string' || typeof t === 'number' || typeof t === 'symbol')
26
- return (procObj as any)[t](t);
27
- else
28
- return (procObj as any)[t.status](t.status,t.result);
29
- }
30
22
  if(false){
23
+ let aaser = assertLiteral({a:1})
24
+
31
25
  let a:"asd"|"dsa" = null as any;
32
- const r = match(a,{
26
+ const r = matchProc(a,{
33
27
  "asd":(a)=>"ssa" as const,
34
28
  "dsa":(b)=>"ssb" as const,
35
29
  })
30
+ let b:Outcome<"a","123">|NoneOut = null as any;
31
+ const r1 = matchProc(b,{
32
+ "a":(a,s)=>"ssa" as const,
33
+ [None]:(b,s)=>"ssb" as const,
34
+ })
35
+ let udt = outcome("ssa","None");
36
+
37
+ type test = Outcome<"a"|"b",any> extends Outcome<"a",12>|Outcome<"b",34>
38
+ ? "suc" : "fal"
39
+ let assa = isFailed(null as any as Failed)
40
+ let assb = isFailed(null as any as Failed|Success)
41
+ let assc = isFailed(null as any as Success)
42
+ let asssc = isFailed(null)
43
+ let assa1 = isFailed(null as any as Outcome<Failed,unknown>)
44
+ let assb1 = isFailed(null as any as Outcome<Failed|Success,unknown>)
45
+ let assc1 = isFailed(null as any as Outcome<Success,unknown>)
46
+
47
+ let proct = sucesProc(null as any as Outcome<Failed|Success,"123">|Outcome<Failed,"1234">|Outcome<Success,"1s23">,
48
+ (s)=>"ssa" as const,
49
+ (f)=>"ssad" as const,
50
+ ()=>123 as const)
51
+
52
+ let matt = matchProc(null as any as Outcome<symbol,123>,{
53
+
54
+ })
36
55
  }
37
56
 
@@ -1,4 +1,5 @@
1
1
  import { UtilFunc } from "./UtilFunctions";
2
+ import { UnwrapPromise } from "./UtilInterfaces";
2
3
  import { SLogger } from "./UtilLogger";
3
4
 
4
5
  type TDTg<T> =
@@ -136,7 +137,7 @@ export function DeferAsync<T extends (...args:any)=>Promise<any>>
136
137
  };
137
138
  }
138
139
  /**try-catch包装 */
139
- export function DCatch<T extends (...args:any)=>any>
140
+ export function Catch<T extends (...args:any)=>any>
140
141
  (catchLogic:(error: any, ...args:Parameters<T>)=>ReturnType<T>):TDTg<T> {
141
142
  return function(target, propertyKey, descriptor) {
142
143
  const originalMethod = descriptor.value!;
@@ -198,6 +199,7 @@ class Example {
198
199
  }
199
200
  @LogCall()
200
201
  @Defer((a,b)=>null)
202
+ @CatchAsync(async (a,b)=>123)
201
203
  static async myMethod1(num: number,ss:string) {
202
204
  return 312;
203
205
  }
@@ -1,19 +1,18 @@
1
1
  import * as crypto from "crypto";
2
- import { ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Mixinable, Outcome, PromiseStat, PromiseVerifyFn } from "@src/UtilInterfaces";
2
+ import { AnyFunc, ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseStat, PromiseVerifyFn, UnionToIntersection } from "@src/UtilInterfaces";
3
3
  import * as cp from "child_process";
4
4
  import { SLogger } from "@src/UtilLogger";
5
- import { Completed, Failed, None, Success, Terminated, Timeout } from "./UtilSymbol";
6
- import { match, outcome } from "./QuickFunction";
7
- import { LogTimeAsync } from "./UtilDecorators";
5
+ import { Completed, Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
6
+ import { DeferAsync, LogTimeAsync } from "./UtilDecorators";
8
7
 
9
8
 
10
- type CompleteCome<T> = Outcome<Completed,T>;
11
- type TimeoutCome<T> = Outcome<Timeout,Promise<T>>;
9
+ type SuccessOut<T> = Outcome<Success,T>;
10
+ type TimeoutOut<T> = Outcome<Timeout,Promise<T>>;
12
11
  /**永不完成的Promise单例 */
13
12
  const NeverResolvedPromise = new Promise(()=>{});
14
- /**进行中的请求 */
15
- type ProcessingPromise<T> = {
16
- /**主体请求 */
13
+ /**完成的请求 */
14
+ type PromiseResult<T> = {
15
+ /**请求结果 */
17
16
  result:T;
18
17
  /**请求状态 */
19
18
  stat:PromiseStat;
@@ -80,24 +79,6 @@ static calcHash(str:string) {
80
79
  return crypto.createHash('md5').update(str).digest('hex');
81
80
  }
82
81
 
83
- /**深克隆 序列化并反序列化
84
- * @template T - JToken类型的泛型
85
- * @param obj - 克隆目标
86
- * @returns 克隆结果
87
- */
88
- static deepClone<T extends JToken>(obj: T): T {
89
- return JSON.parse(JSON.stringify(obj));
90
- }
91
-
92
- /**是否为安全的数字
93
- * @param num - 所要检测的数字
94
- * @returns 是否安全
95
- */
96
- static isSafeNumber(num: number): boolean {
97
- if (num === undefined || num == null || isNaN(num)) return false;
98
- if(typeof num === 'number') return true;
99
- return false;
100
- }
101
82
 
102
83
  /**等待 timeMs 毫秒
103
84
  * @async
@@ -146,7 +127,7 @@ static getNeverResolvedPromise<T>():Promise<T>{
146
127
  * @param procFn - 发起函数
147
128
  * @param verifyFn - 验证函数
148
129
  * @param repeatCount - 重试次数
149
- * @param repeatTime - 超时时间/秒 最小为10
130
+ * @param repeatTime - 超时时间/秒 最小为5
150
131
  * @returns 结果 null 为全部失败/超时
151
132
  */
152
133
  @LogTimeAsync("repeatPromise ",true)
@@ -154,7 +135,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
154
135
  repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
155
136
 
156
137
  /**是否含有超时时间 */
157
- const hasRepeatTime = (repeatTime>=10);
138
+ const hasRepeatTime = (repeatTime>=5);
158
139
  //转换为毫秒
159
140
  if(hasRepeatTime) repeatTime*=1000;
160
141
 
@@ -164,8 +145,8 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
164
145
 
165
146
  //进行中的请求
166
147
  const plist:Promise<
167
- CompleteCome<ProcessingPromise<T>>|
168
- TimeoutCome<ProcessingPromise<T>>
148
+ SuccessOut<PromiseResult<T>>|
149
+ TimeoutOut<PromiseResult<T>>
169
150
  >[] = [];
170
151
 
171
152
  //开始处理
@@ -176,7 +157,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
176
157
 
177
158
  //如果 plist 中当前下标的任务还未创建 则 创建当前任务
178
159
  if(plist.length<i+1){
179
- plist.push(UtilFunc.timelimitPromise<ProcessingPromise<T>>(async ()=>{
160
+ plist.push(UtilFunc.timelimitPromise<PromiseResult<T>>(async ()=>{
180
161
  const index = i;
181
162
  const result = await procFn();
182
163
  const stat = await verifyFn!(result);
@@ -192,7 +173,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
192
173
  //解除timeout替换原参数
193
174
  plist[i]=new Promise(async (rslove)=>{
194
175
  const res = await currObj.result;
195
- rslove(outcome(Completed,res));
176
+ rslove(UtilFunc.outcome(Success,res));
196
177
  })
197
178
  SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
198
179
  i++;
@@ -201,7 +182,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
201
182
 
202
183
  //路由请求状态
203
184
  const postresult = currObj.result;
204
- const result = match(postresult.stat,{
185
+ const result = UtilFunc.matchProc(postresult.stat,{
205
186
  [Success](){
206
187
  SLogger.info(`第 ${postresult.index+1} 次 repeatPromise 成功`);
207
188
  //非当前
@@ -245,29 +226,29 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
245
226
  * @returns 超时则返回 处理函数委托 完成则返回结果
246
227
  */
247
228
  static timelimitPromise<T>
248
- (func:()=>Promise<T>|T,timeLimit?:number):Promise<CompleteCome<T>|TimeoutCome<T>>{
249
- return new Promise<CompleteCome<T>|TimeoutCome<T>>((reslove)=>{
229
+ (func:()=>Promise<T>|T,timeLimit?:number):Promise<SuccessOut<T>|TimeoutOut<T>>{
230
+ return new Promise<SuccessOut<T>|TimeoutOut<T>>((reslove)=>{
250
231
  let clearTimer:(()=>void)| null = null;
251
232
  const procer = (async ()=>await func())();
252
233
 
253
- const procerP = new Promise<CompleteCome<T>>(async (resolve)=>{
234
+ const procerP = new Promise<SuccessOut<T>>(async (resolve)=>{
254
235
  const res = await procer;
255
- resolve(outcome(Completed,res));
236
+ resolve(UtilFunc.outcome(Success,res));
256
237
  if(clearTimer) clearTimer();
257
238
  });
258
239
 
259
240
  const timerP = timeLimit
260
- ? new Promise<TimeoutCome<T>>((resolve)=>{
241
+ ? new Promise<TimeoutOut<T>>((resolve)=>{
261
242
  const timer = setTimeout(()=>
262
- resolve(outcome(Timeout,procer))
243
+ resolve(UtilFunc.outcome(Timeout,procer))
263
244
  ,timeLimit);//无限制则无限时间
264
245
 
265
246
  clearTimer = ()=>{
266
- resolve(outcome(Timeout,procer))
247
+ resolve(UtilFunc.outcome(Timeout,procer))
267
248
  clearInterval(timer)
268
249
  }
269
- })
270
- : UtilFunc.getNeverResolvedPromise<TimeoutCome<T>>();
250
+ })//未定义时间限制则无限
251
+ : UtilFunc.getNeverResolvedPromise<TimeoutOut<T>>();
271
252
 
272
253
  const result = Promise.race([procerP,timerP]);
273
254
  reslove(result);
@@ -346,7 +327,7 @@ static composeMixinable
346
327
  * @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
347
328
  * @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
348
329
  */
349
- static mapEntries<T extends Object>
330
+ static mapEntries<T extends object>
350
331
  (obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
351
332
  return Object.entries(obj).reduce((result, [key, value]) => {
352
333
  result[key as keyof T] = mapper(key as keyof T, value);
@@ -365,4 +346,162 @@ static stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\
365
346
  return JSON.stringify(token,null,space);
366
347
  }
367
348
 
349
+ /**代办表 用于队列处理等待 */
350
+ static pendingMap:Record<Keyable,AnyFunc[]> = {};
351
+
352
+ /**队列处理
353
+ * 等待标签为 flag 的队列
354
+ * 直到排在之前的任务全部完成再处理当前Promise
355
+ * @param flag - 队列标签
356
+ * @param task - 任务逻辑
357
+ * @returns 处理结果
358
+ */
359
+ static async queueProc<T>(flag:Keyable,task:(()=>Promise<T>)|Promise<T>):Promise<T> {
360
+ this.pendingMap[flag] = this.pendingMap[flag]??[];
361
+ const pending = this.pendingMap[flag];
362
+
363
+ //尝试解除下个任务的等待
364
+ const tryRes = function(){
365
+ const thispd = pending;
366
+ const resolve = thispd.shift();
367
+ if(resolve) resolve();
368
+ }
369
+
370
+ //空时直接运行 非空时等待
371
+ if (pending.length <= 0)
372
+ pending.push(()=>tryRes());
373
+ else await new Promise((resolve) => pending.push(resolve));
374
+
375
+ try {
376
+ const result = typeof task === 'function'
377
+ ? await task()
378
+ : await task;
379
+ return result;
380
+ } catch(e){
381
+ SLogger.fatal(`queuePromise 出现错误`,e);
382
+ throw e;
383
+ }finally {
384
+ tryRes();
385
+ }
386
+ }
387
+
388
+
389
+
390
+ /**创建一个Outcome */
391
+ static outcome<K extends Keyable,V> (key:K,value:V):Outcome<K,V>{
392
+ return {
393
+ status:key,
394
+ result:value
395
+ }
396
+ }
397
+
398
+
399
+ /**处理联合值
400
+ * @param t - 目标值
401
+ * @param procObj - 所有可能的id组成的处理函数映射 (status, result)=>any
402
+ * @returns 任意处理函数的返回值
403
+ */
404
+ static matchProc<
405
+ T extends Matchable<Keyable>,
406
+ P extends UnionToIntersection<
407
+ { [K in MatchableFlag<T>] :
408
+ (k:K,v:ExtractOutcome<T,MatchableFlag<K>>['result'])=>unknown }>>
409
+ (t:T, procObj:P):
410
+ P extends Record<any,AnyFunc>
411
+ ? {[K in keyof P]: ReturnType<P[K]>}[keyof P]
412
+ : never {
413
+ if (typeof t === 'string' || typeof t === 'number' || typeof t === 'symbol'){
414
+ if ((procObj as any)[t])
415
+ return (procObj as any)[t](t);
416
+ SLogger.fatal(`matchProc 传入了一个预料之外的值: `,t);
417
+ throw None;
418
+ }
419
+ else{
420
+ if ((procObj as any)[t.status])
421
+ return (procObj as any)[t.status](t.status,(t as any).result);
422
+ SLogger.fatal(`matchProc 传入了一个预料之外的值: `,t);
423
+ throw None;
424
+ }
425
+ }
426
+
427
+ /**根据典型的成功或失败状态运行函数
428
+ * @param t - 目标值
429
+ * @param sucessFunc - 成功则运行的函数 (result)=>any
430
+ * @param failedFunc - 失败则运行的函数 (result)=>any
431
+ * @param noneFunc - 无结果或不匹配时运行的函数 ()=>any
432
+ * @returns 非成功或失败时返回 None
433
+ */
434
+ static sucesProc<T extends Matchable<StatusSymbol>,
435
+ S extends (arg:ExtractOutcome<T,SuccessLike>['result'])=>unknown,
436
+ F extends (arg:ExtractOutcome<T,FailedLike>['result'])=>unknown =
437
+ (arg:ExtractOutcome<T,FailedLike>['result'])=>None,
438
+ N extends ()=>unknown = ()=>None>
439
+ (t:T,sucessFunc:S,failedFunc?:F,noneFunc?:N):
440
+ ReturnType<S>|ReturnType<F>|ReturnType<N>{
441
+ failedFunc = failedFunc ?? (()=>None) as any as F;
442
+ noneFunc = noneFunc ?? (()=>None) as N;
443
+ const val = typeof t === 'symbol' ? undefined : t.result;
444
+ if(UtilFunc.isSuccess(t)) return sucessFunc(val) as any;
445
+ if(UtilFunc.isFailed(t)) return failedFunc(val) as any;
446
+ if(t!==None) SLogger.warn(`sucesProc 传入了一个不匹配的值, 将作为None运行: `,t);
447
+ return noneFunc() as any;
448
+ }
449
+ /**是失败的 */
450
+ static isFailed<T>
451
+ (tg:T):T extends Matchable<FailedLike>
452
+ ? true : MatchableFlag<T> extends Exclude<MatchableFlag<T>,FailedLike>
453
+ ? false : boolean{
454
+ const test = (t:any)=>t === Failed || t === Terminated || t === Timeout;
455
+ if(tg!=null && typeof tg === 'object' && 'status' in tg)
456
+ return test(tg.status) as any
457
+ return test(tg) as any
458
+ }
459
+
460
+ /**是成功的 */
461
+ static isSuccess<T>
462
+ (tg:T):T extends Matchable<SuccessLike>
463
+ ? true: MatchableFlag<T> extends Exclude<MatchableFlag<T>,SuccessLike>
464
+ ? false : boolean{
465
+ const test = (t:any)=>t === Success || t === Completed;
466
+ if(tg!=null && typeof tg === 'object' && 'status' in tg)
467
+ return test(tg.status) as any
468
+ return test(tg) as any
469
+ }
470
+
471
+ /**验证一个变量的类型是否为 T
472
+ * @template T - 验证类型
473
+ * @param t - 验证目标
474
+ */
475
+ static assertType<T>(t:T):T{return t;}
476
+ /**验证一个变量的类型是否为字面量
477
+ * 仅限浅层
478
+ * @template T - 验证类型
479
+ * @param t - 验证目标
480
+ */
481
+ static assertLiteral<T>(t:LiteralCheck<T>):T{return t as T;}
482
+
483
+ /**深克隆 序列化并反序列化
484
+ * @template T - JToken类型的泛型
485
+ * @param obj - 克隆目标
486
+ * @returns 克隆结果
487
+ */
488
+ static deepClone<T extends JToken>(obj: T): T {
489
+ return JSON.parse(JSON.stringify(obj));
490
+ }
491
+
492
+ /**是否为安全的数字
493
+ * 非NaN 非null/undefined
494
+ * 且是数字
495
+ * @param num - 所要检测的数字
496
+ * @returns 是否安全
497
+ */
498
+ static isSafeNumber(num: unknown): boolean {
499
+ if (num == null) return false;
500
+ if(typeof num === 'number') {
501
+ if(isNaN(num)) return false;
502
+ return true;
503
+ }
504
+ return false;
505
+ }
506
+
368
507
  }