@zwa73/utils 1.0.43 → 1.0.45

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/UtilCom.d.ts CHANGED
@@ -1,22 +1,46 @@
1
- import { JObject } from "./UtilInterfaces";
1
+ import { JObject, PromiseVerifyFn } from "./UtilInterfaces";
2
2
  /**网络工具 */
3
3
  export declare namespace UtilCom {
4
- /**发送一个POST请求并接受数据
4
+ /**发送一个 https POST请求并接受数据
5
5
  * Object ()
6
6
  * @async
7
7
  * @param {JObject} json - 数据对象
8
8
  * @param {Object} options - 参数对象
9
9
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
10
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
10
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
11
11
  */
12
12
  function shttpsPost(json: JObject, options: Object, timeLimit?: number): Promise<JObject | null>;
13
- /**发送一个POST请求并接受数据
13
+ /**发送一个 http POST请求并接受数据
14
14
  * Object ()
15
15
  * @async
16
16
  * @param {JObject} json - 数据对象
17
17
  * @param {Object} options - 参数对象
18
18
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
19
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
19
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
20
20
  */
21
21
  function shttpPost(json: JObject, options: Object, timeLimit?: number): Promise<JObject | null>;
22
+ /**重复一个 https POST请求并接受数据
23
+ * Object ()
24
+ * @async
25
+ * @param {JObject} json - 数据对象
26
+ * @param {Object} options - 参数对象
27
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
28
+ * @param {number} [repeatCount] - 重试次数
29
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
30
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
31
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
32
+ */
33
+ function shttpsRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: PromiseVerifyFn<JObject | null>): Promise<JObject | null>;
34
+ /**重复一个 http POST请求并接受数据
35
+ * Object ()
36
+ * @async
37
+ * @param {JObject} json - 数据对象
38
+ * @param {Object} options - 参数对象
39
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
40
+ * @param {number} [repeatCount] - 重试次数
41
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
42
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
43
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
44
+ */
45
+ function shttpRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: PromiseVerifyFn<JObject | null>): Promise<JObject | null>;
22
46
  }
package/dist/UtilCom.js CHANGED
@@ -5,16 +5,24 @@ const UtilInterfaces_1 = require("./UtilInterfaces");
5
5
  const https = require("https");
6
6
  const http = require("http");
7
7
  const UtilLogger_1 = require("./UtilLogger");
8
+ const UtilFunctions_1 = require("./UtilFunctions");
8
9
  /**网络工具 */
9
10
  var UtilCom;
10
11
  (function (UtilCom) {
11
- function sPost(type, json, options, timeLimit = -1) {
12
+ /**通用post处理
13
+ * @param {"http"|"https"} posttype - post类型
14
+ * @param {JObject} json - 数据对象
15
+ * @param {Object} options - 参数对象
16
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
17
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
18
+ */
19
+ function sPost(posttype, json, options, timeLimit = -1) {
12
20
  //转换为毫秒
13
21
  const hasTimeLimit = (timeLimit >= 10);
14
22
  if (hasTimeLimit)
15
23
  timeLimit *= 1000;
16
24
  const jsonStr = (0, UtilInterfaces_1.stringifyJToken)(json);
17
- const funcName = "s" + type + "Psot";
25
+ const funcName = "s" + posttype + "Psot";
18
26
  return new Promise((resolve, rejecte) => {
19
27
  const resFunc = (res) => {
20
28
  try {
@@ -62,9 +70,9 @@ var UtilCom;
62
70
  };
63
71
  //路由 http/https
64
72
  let req = null;
65
- if (type === "https")
73
+ if (posttype === "https")
66
74
  req = https.request(options, resFunc);
67
- else if (type === "http")
75
+ else if (posttype === "http")
68
76
  req = http.request(options, resFunc);
69
77
  //请求超时
70
78
  if (hasTimeLimit) {
@@ -81,28 +89,73 @@ var UtilCom;
81
89
  req.end();
82
90
  });
83
91
  }
84
- /**发送一个POST请求并接受数据
92
+ /**发送一个 https POST请求并接受数据
85
93
  * Object ()
86
94
  * @async
87
95
  * @param {JObject} json - 数据对象
88
96
  * @param {Object} options - 参数对象
89
97
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
90
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
98
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
91
99
  */
92
100
  function shttpsPost(json, options, timeLimit = -1) {
93
101
  return sPost("https", json, options, timeLimit);
94
102
  }
95
103
  UtilCom.shttpsPost = shttpsPost;
96
- /**发送一个POST请求并接受数据
104
+ /**发送一个 http POST请求并接受数据
97
105
  * Object ()
98
106
  * @async
99
107
  * @param {JObject} json - 数据对象
100
108
  * @param {Object} options - 参数对象
101
109
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
102
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
110
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
103
111
  */
104
112
  function shttpPost(json, options, timeLimit = -1) {
105
113
  return sPost("http", json, options, timeLimit);
106
114
  }
107
115
  UtilCom.shttpPost = shttpPost;
116
+ /**通用重复post处理
117
+ * @async
118
+ * @param {"http"|"https"} posttype - post类型
119
+ * @param {JObject} json - 数据对象
120
+ * @param {Object} options - 参数对象
121
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
122
+ * @param {number} [repeatCount] - 重试次数
123
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
124
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
125
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
126
+ */
127
+ async function sRepeatPost(posttype, json, options, timeLimit = -1, repeatCount = 3, repeatTime = 180, verifyFn) {
128
+ const procFn = () => sPost(posttype, json, options, timeLimit);
129
+ return UtilFunctions_1.UtilFunc.repeatPromise(procFn, verifyFn, repeatCount, repeatTime);
130
+ }
131
+ /**重复一个 https POST请求并接受数据
132
+ * Object ()
133
+ * @async
134
+ * @param {JObject} json - 数据对象
135
+ * @param {Object} options - 参数对象
136
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
137
+ * @param {number} [repeatCount] - 重试次数
138
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
139
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
140
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
141
+ */
142
+ function shttpsRepeatPost(json, options, timeLimit = -1, repeatCount = 3, repeatTime = 180, verifyFn) {
143
+ return sRepeatPost("https", json, options, timeLimit, repeatCount, repeatTime, verifyFn);
144
+ }
145
+ UtilCom.shttpsRepeatPost = shttpsRepeatPost;
146
+ /**重复一个 http POST请求并接受数据
147
+ * Object ()
148
+ * @async
149
+ * @param {JObject} json - 数据对象
150
+ * @param {Object} options - 参数对象
151
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
152
+ * @param {number} [repeatCount] - 重试次数
153
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
154
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
155
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
156
+ */
157
+ function shttpRepeatPost(json, options, timeLimit = -1, repeatCount = 3, repeatTime = 180, verifyFn) {
158
+ return sRepeatPost("http", json, options, timeLimit, repeatCount, repeatTime, verifyFn);
159
+ }
160
+ UtilCom.shttpRepeatPost = shttpRepeatPost;
108
161
  })(UtilCom = exports.UtilCom || (exports.UtilCom = {}));
@@ -1,4 +1,4 @@
1
- import { JToken } from "./UtilInterfaces";
1
+ import { JToken, PromiseProcFn, PromiseVerifyFn } from "./UtilInterfaces";
2
2
  /**常用函数 */
3
3
  export declare namespace UtilFunc {
4
4
  /**获取当前时间戳
@@ -51,4 +51,6 @@ export declare namespace UtilFunc {
51
51
  }>;
52
52
  /**获得一个永不完成的Promise单例 */
53
53
  function getNeverResolvedPromise<T>(): Promise<T>;
54
+ /**重复尝试promise */
55
+ function repeatPromise<T>(procFn: PromiseProcFn<T>, verifyFn?: PromiseVerifyFn<T>, repeatCount?: number, repeatTime?: number): Promise<T | null>;
54
56
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UtilFunc = void 0;
4
4
  const crypto = require("crypto");
5
5
  const cp = require("child_process");
6
+ const UtilLogger_1 = require("./UtilLogger");
6
7
  /**常用函数 */
7
8
  var UtilFunc;
8
9
  (function (UtilFunc) {
@@ -98,4 +99,82 @@ var UtilFunc;
98
99
  return NeverResolvedPromise;
99
100
  }
100
101
  UtilFunc.getNeverResolvedPromise = getNeverResolvedPromise;
102
+ /**重复尝试promise */
103
+ async function repeatPromise(procFn, verifyFn, repeatCount = 3, repeatTime = 180) {
104
+ //转换为毫秒
105
+ const hasRepeatTime = (repeatTime >= 10);
106
+ if (hasRepeatTime)
107
+ repeatTime *= 1000;
108
+ //验证处理函数
109
+ if (verifyFn === undefined)
110
+ verifyFn = () => "Completed";
111
+ //计时器
112
+ let timer = null;
113
+ let timerP = null;
114
+ let resolveFn = null;
115
+ /**清理计时器 */
116
+ const clearTimer = () => {
117
+ if (timer != null)
118
+ clearInterval(timer);
119
+ if (resolveFn != null)
120
+ resolveFn("Timeout");
121
+ timerP = null;
122
+ timer = null;
123
+ resolveFn = null;
124
+ };
125
+ //进行中的请求
126
+ const plist = new Array(repeatCount)
127
+ .fill(UtilFunc.getNeverResolvedPromise());
128
+ for (let i = 0; i < repeatCount;) {
129
+ UtilLogger_1.SLogger.info("开始第 " + (i + 1) + " 次 repeatPromise");
130
+ //创建当前任务
131
+ plist[i] = procFn().then(result => ({ result, stat: verifyFn(result), index: i }));
132
+ //创建定时器
133
+ if (timerP == null) {
134
+ timerP = new Promise(function (resolve, rejecte) {
135
+ resolveFn = resolve;
136
+ timer = setTimeout(() => resolve("Timeout"), hasRepeatTime ? repeatTime : Infinity); //无限制则无限时间
137
+ });
138
+ }
139
+ //等待完成
140
+ const currObj = await Promise.race([...plist, timerP]);
141
+ //超时处理
142
+ if (currObj == "Timeout") {
143
+ UtilLogger_1.SLogger.warn(`第 ${(i + 1)} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
144
+ clearTimer();
145
+ i++;
146
+ continue;
147
+ }
148
+ else {
149
+ const poststat = await currObj.stat;
150
+ switch (poststat) {
151
+ case "Completed": //完成
152
+ UtilLogger_1.SLogger.info("第 " + (currObj.index + 1) + " 次 repeatPromise 成功");
153
+ clearTimer();
154
+ return currObj.result;
155
+ case "Terminated": //终止
156
+ UtilLogger_1.SLogger.warn("第 " + (currObj.index + 1) + " 次 repeatPromise 终止 停止重试");
157
+ clearTimer();
158
+ return currObj.result;
159
+ case "Failed": //验证失败
160
+ //是当前
161
+ if (currObj.index == i) {
162
+ UtilLogger_1.SLogger.warn("第 " + (currObj.index + 1) + " 次 repeatPromise 失败 开始重试");
163
+ clearTimer();
164
+ i++;
165
+ continue;
166
+ }
167
+ //非当前
168
+ UtilLogger_1.SLogger.warn("第 " + (currObj.index + 1) + " 次 repeatPromise 失败");
169
+ //抛弃失败
170
+ plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
171
+ continue;
172
+ }
173
+ }
174
+ }
175
+ clearTimer();
176
+ //全部失败或超时则返回null
177
+ return null;
178
+ }
179
+ UtilFunc.repeatPromise = repeatPromise;
101
180
  })(UtilFunc = exports.UtilFunc || (exports.UtilFunc = {}));
@@ -54,4 +54,22 @@ type ExclusiveRecursive<B, T, K extends string[], R extends unknown[] = []> = R[
54
54
  export type ExclusiveRecord<B, T, K extends string[], TMP = ExclusiveRecursive<B, T, K>> = TMP[keyof TMP];
55
55
  /**符合JObject约束的互斥表 */
56
56
  export type ExclusiveJObject<B extends JObject, T extends JToken, K extends string[], TMP extends JArray = ExclusiveRecursive<B, T, K>> = TMP[number];
57
+ /**进行中的请求 */
58
+ export type ProcessingPromise<T> = {
59
+ /**主体请求 */
60
+ result: T;
61
+ /**请求状态 */
62
+ stat: PromiseStat | Promise<PromiseStat>;
63
+ /**请求下标/序号 */
64
+ index: number;
65
+ };
66
+ /**请求完成状态 成功/失败/终止
67
+ * 成功/终止 将直接返回
68
+ * 失败 将重试
69
+ */
70
+ export type PromiseStat = "Completed" | "Failed" | "Terminated";
71
+ /**promise验证函数 */
72
+ export type PromiseVerifyFn<T> = (obj: T) => Promise<PromiseStat> | PromiseStat;
73
+ /**发起promise的函数 */
74
+ export type PromiseProcFn<T> = () => Promise<T>;
57
75
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/utils",
3
- "version": "1.0.43",
3
+ "version": "1.0.45",
4
4
  "description": "my utils",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/UtilCom.ts CHANGED
@@ -1,20 +1,28 @@
1
- import { JObject, stringifyJToken } from "./UtilInterfaces";
1
+ import { JObject, ProcessingPromise, PromiseVerifyFn, stringifyJToken } from "./UtilInterfaces";
2
2
  import * as https from 'https';
3
3
  import * as http from 'http';
4
4
  import { SLogger } from "./UtilLogger";
5
+ import { UtilFunc } from "./UtilFunctions";
5
6
 
6
7
 
7
8
  /**网络工具 */
8
9
  export namespace UtilCom{
9
10
 
10
- function sPost(type:"http"|"https",json:JObject,options:Object,timeLimit:number=-1):Promise<JObject|null>{
11
+ /**通用post处理
12
+ * @param {"http"|"https"} posttype - post类型
13
+ * @param {JObject} json - 数据对象
14
+ * @param {Object} options - 参数对象
15
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
16
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
17
+ */
18
+ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:number=-1):Promise<JObject|null>{
11
19
  //转换为毫秒
12
20
  const hasTimeLimit = (timeLimit>=10);
13
21
  if(hasTimeLimit)
14
22
  timeLimit*=1000
15
23
 
16
24
  const jsonStr = stringifyJToken(json);
17
- const funcName = "s"+type+"Psot";
25
+ const funcName = "s"+posttype+"Psot";
18
26
 
19
27
  return new Promise((resolve, rejecte)=>{
20
28
  const resFunc = (res:http.IncomingMessage)=>{
@@ -65,9 +73,9 @@ function sPost(type:"http"|"https",json:JObject,options:Object,timeLimit:number=
65
73
  };
66
74
  //路由 http/https
67
75
  let req:http.ClientRequest=null as any as http.ClientRequest;
68
- if(type === "https")
76
+ if(posttype === "https")
69
77
  req = https.request(options, resFunc);
70
- else if(type === "http")
78
+ else if(posttype === "http")
71
79
  req = http.request(options, resFunc);
72
80
 
73
81
  //请求超时
@@ -88,27 +96,80 @@ function sPost(type:"http"|"https",json:JObject,options:Object,timeLimit:number=
88
96
  });
89
97
  }
90
98
 
91
- /**发送一个POST请求并接受数据
92
- * Object ()
99
+ /**发送一个 https POST请求并接受数据
100
+ * Object ()
93
101
  * @async
94
102
  * @param {JObject} json - 数据对象
95
103
  * @param {Object} options - 参数对象
96
104
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
97
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
105
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
98
106
  */
99
107
  export function shttpsPost(json:JObject,options:Object,timeLimit:number=-1):Promise<JObject|null>{
100
108
  return sPost("https",json,options,timeLimit);
101
109
  }
102
110
 
103
- /**发送一个POST请求并接受数据
104
- * Object ()
111
+ /**发送一个 http POST请求并接受数据
112
+ * Object ()
105
113
  * @async
106
114
  * @param {JObject} json - 数据对象
107
115
  * @param {Object} options - 参数对象
108
116
  * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
109
- * @returns {Promise<Object|null>} 结果 null 为未能成功接收
117
+ * @returns {Promise<JObject|null>} 结果 null 为未能成功接收
110
118
  */
111
119
  export function shttpPost(json:JObject,options:Object,timeLimit:number=-1):Promise<JObject|null>{
112
120
  return sPost("http",json,options,timeLimit);
113
121
  }
122
+
123
+
124
+
125
+ /**通用重复post处理
126
+ * @async
127
+ * @param {"http"|"https"} posttype - post类型
128
+ * @param {JObject} json - 数据对象
129
+ * @param {Object} options - 参数对象
130
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
131
+ * @param {number} [repeatCount] - 重试次数
132
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
133
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
134
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
135
+ */
136
+ async function sRepeatPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:number=-1,
137
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
138
+ const procFn = ()=>sPost(posttype,json,options,timeLimit);
139
+ return UtilFunc.repeatPromise(procFn,verifyFn,repeatCount,repeatTime);
140
+ }
141
+
142
+
143
+ /**重复一个 https POST请求并接受数据
144
+ * Object ()
145
+ * @async
146
+ * @param {JObject} json - 数据对象
147
+ * @param {Object} options - 参数对象
148
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
149
+ * @param {number} [repeatCount] - 重试次数
150
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
151
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
152
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
153
+ */
154
+ export function shttpsRepeatPost(json:JObject,options:Object,timeLimit:number=-1,
155
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
156
+ return sRepeatPost("https",json,options,timeLimit,repeatCount,repeatTime,verifyFn);
157
+ }
158
+
159
+ /**重复一个 http POST请求并接受数据
160
+ * Object ()
161
+ * @async
162
+ * @param {JObject} json - 数据对象
163
+ * @param {Object} options - 参数对象
164
+ * @param {number} [timeLimit] - 超时时间/秒 最小为10秒
165
+ * @param {number} [repeatCount] - 重试次数
166
+ * @param {number} [repeatTime] - 超时时间/秒 最小为10秒
167
+ * @param {PromiseVerifyFn<JObject|null>} [verifyFn] - 判断有效性函数
168
+ * @returns {Promise<JObject|null>} - 结果 null 为未能成功接收
169
+ */
170
+ export function shttpRepeatPost(json:JObject,options:Object,timeLimit:number=-1,
171
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
172
+ return sRepeatPost("http",json,options,timeLimit,repeatCount,repeatTime,verifyFn);
173
+ }
174
+
114
175
  }
@@ -1,19 +1,20 @@
1
1
  import * as crypto from "crypto";
2
- import { JToken } from "./UtilInterfaces";
2
+ import { JToken, ProcessingPromise, PromiseProcFn, PromiseVerifyFn } from "./UtilInterfaces";
3
3
  import * as cp from "child_process";
4
+ import { SLogger } from "./UtilLogger";
4
5
 
5
6
  /**常用函数 */
6
7
  export namespace UtilFunc{
7
- /**获取当前时间戳
8
- * number ()
8
+ /**获取当前时间戳
9
+ * number ()
9
10
  * @returns {number} 时间戳
10
11
  */
11
12
  export function getTime(): number {
12
13
  return new Date().getTime();
13
14
  }
14
15
 
15
- /**初始化对象的字段
16
- * void (Object,string,any)
16
+ /**初始化对象的字段
17
+ * void (Object,string,any)
17
18
  * @param {Record<string,T>} obj - 所要初始化的对象
18
19
  * @param {string} field - 所要初始化的字段
19
20
  * @param {T} defaultVal - 默认值
@@ -28,15 +29,15 @@ export function initField<T>(
28
29
  return obj[field];
29
30
  }
30
31
 
31
- /**生成一串uuid
32
- * string ()
32
+ /**生成一串uuid
33
+ * string ()
33
34
  * @returns {string} uuid
34
35
  */
35
36
  export function genUUID() {
36
37
  return crypto.randomBytes(16).toString("hex");
37
38
  }
38
- /**计算Hash
39
- * string ()
39
+ /**计算Hash
40
+ * string ()
40
41
  * @param {string} str - 待计算的字符串
41
42
  * @returns {string} hash
42
43
  */
@@ -44,7 +45,7 @@ export function calcHash(str:string) {
44
45
  return crypto.createHash('md5').update(str).digest('hex');
45
46
  }
46
47
 
47
- /**深克隆 序列化并反序列化
48
+ /**深克隆 序列化并反序列化
48
49
  * @template {T} T - JToken类型的泛型
49
50
  * @param {T} obj - 克隆目标
50
51
  * @returns {T} 克隆结果
@@ -63,7 +64,7 @@ export function isSafeNumber(num: number): boolean {
63
64
  return false;
64
65
  }
65
66
 
66
- /**等待 timeMs 毫秒
67
+ /**等待 timeMs 毫秒
67
68
  * @async
68
69
  * @param {number} timeMs - 等待的毫秒数
69
70
  * @returns {Promise<boolean>}
@@ -76,7 +77,7 @@ export async function sleep(timeMs: number): Promise<boolean> {
76
77
  });
77
78
  }
78
79
 
79
- /**封装的 cp.exec 执行一段指令 指令完成后返回 Promise
80
+ /**封装的 cp.exec 执行一段指令 指令完成后返回 Promise
80
81
  * @param {string} command 指令文本
81
82
  */
82
83
  export function exec(command: string) {
@@ -97,5 +98,88 @@ export function getNeverResolvedPromise<T>():Promise<T>{
97
98
  return NeverResolvedPromise as Promise<T>;
98
99
  }
99
100
 
101
+ /**重复尝试promise */
102
+ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:PromiseVerifyFn<T>,
103
+ repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
104
+ //转换为毫秒
105
+ const hasRepeatTime = (repeatTime>=10);
106
+ if(hasRepeatTime) repeatTime*=1000;
107
+
108
+ //验证处理函数
109
+ if(verifyFn===undefined)
110
+ verifyFn = ()=>"Completed";
111
+
112
+ //计时器
113
+ let timer:NodeJS.Timer|null = null;
114
+ let timerP:Promise<"Timeout">|null=null;
115
+ let resolveFn:((value: "Timeout" | PromiseLike<"Timeout">)=>void)|null = null;
116
+ /**清理计时器 */
117
+ const clearTimer = ()=>{
118
+ if(timer!=null)
119
+ clearInterval(timer);
120
+ if(resolveFn!=null)
121
+ resolveFn("Timeout");
122
+ timerP=null;
123
+ timer=null;
124
+ resolveFn=null;
125
+ }
126
+
127
+ //进行中的请求
128
+ const plist:Promise<ProcessingPromise<T>>[] = new Array(repeatCount)
129
+ .fill(UtilFunc.getNeverResolvedPromise());
130
+ for(let i=0;i<repeatCount;){
131
+ SLogger.info("开始第 "+(i+1)+" 次 repeatPromise");
132
+ //创建当前任务
133
+ plist[i] = procFn().then(result =>
134
+ ({result, stat:verifyFn!(result), index:i}));
135
+
136
+ //创建定时器
137
+ if(timerP==null){
138
+ timerP = new Promise<"Timeout">(function(resolve, rejecte){
139
+ resolveFn = resolve;
140
+ timer = setTimeout(()=>resolve("Timeout"),
141
+ hasRepeatTime? repeatTime:Infinity);//无限制则无限时间
142
+ })
143
+ }
144
+
145
+ //等待完成
146
+ const currObj = await Promise.race([...plist, timerP]);
147
+
148
+ //超时处理
149
+ if(currObj=="Timeout"){
150
+ SLogger.warn(`第 ${(i+1)} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
151
+ clearTimer(); i++;
152
+ continue;
153
+ }else{
154
+ const poststat = await currObj.stat;
155
+ switch(poststat){
156
+ case "Completed"://完成
157
+ SLogger.info("第 "+(currObj.index+1)+" 次 repeatPromise 成功");
158
+ clearTimer();
159
+ return currObj.result;
160
+ case "Terminated"://终止
161
+ SLogger.warn("第 "+(currObj.index+1)+" 次 repeatPromise 终止 停止重试");
162
+ clearTimer();
163
+ return currObj.result;
164
+ case "Failed"://验证失败
165
+ //是当前
166
+ if(currObj.index==i){
167
+ SLogger.warn("第 "+(currObj.index+1)+" 次 repeatPromise 失败 开始重试");
168
+ clearTimer(); i++;
169
+ continue;
170
+ }
171
+ //非当前
172
+ SLogger.warn("第 "+(currObj.index+1)+" 次 repeatPromise 失败");
173
+ //抛弃失败
174
+ plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
175
+ continue;
176
+ }
177
+ }
178
+ }
179
+ clearTimer();
180
+ //全部失败或超时则返回null
181
+ return null;
182
+ }
183
+
100
184
  }
101
185
 
@@ -70,3 +70,24 @@ export type ExclusiveRecord<B, T, K extends string[], TMP = ExclusiveRecursive<B
70
70
  /**符合JObject约束的互斥表 */
71
71
  export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string[],
72
72
  TMP extends JArray = ExclusiveRecursive<B,T,K>> = TMP[number];
73
+
74
+
75
+ /**进行中的请求 */
76
+ export type ProcessingPromise<T> = {
77
+ /**主体请求 */
78
+ result:T;
79
+ /**请求状态 */
80
+ stat:PromiseStat|Promise<PromiseStat>;
81
+ /**请求下标/序号 */
82
+ index:number;
83
+ };
84
+
85
+ /**请求完成状态 成功/失败/终止
86
+ * 成功/终止 将直接返回
87
+ * 失败 将重试
88
+ */
89
+ export type PromiseStat = "Completed"|"Failed"|"Terminated";
90
+ /**promise验证函数 */
91
+ export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
92
+ /**发起promise的函数 */
93
+ export type PromiseProcFn<T> = ()=>Promise<T>;