@zwa73/utils 1.0.198 → 1.0.200
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 +150 -61
- package/dist/UtilCom.js +178 -86
- package/dist/UtilFileTools.d.ts +0 -1
- package/dist/UtilFileTools.js +0 -1
- package/dist/UtilFunctions.d.ts +11 -7
- package/dist/UtilFunctions.js +27 -23
- package/dist/UtilInterfaces.d.ts +7 -7
- package/package.json +2 -1
- package/src/UtilCom.macro.ts +28 -0
- package/src/UtilCom.ts +227 -124
- package/src/UtilFileTools.ts +0 -1
- package/src/UtilFunctions.ts +39 -27
- package/src/UtilInterfaces.ts +9 -11
package/dist/UtilCom.js
CHANGED
|
@@ -4,21 +4,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.UtilCom = void 0;
|
|
7
|
-
const https_1 = __importDefault(require("https"));
|
|
8
7
|
const http_1 = __importDefault(require("http"));
|
|
8
|
+
const https_1 = __importDefault(require("https"));
|
|
9
9
|
const UtilLogger_1 = require("./UtilLogger");
|
|
10
10
|
const UtilFunctions_1 = require("./UtilFunctions");
|
|
11
11
|
const querystring_1 = __importDefault(require("querystring"));
|
|
12
12
|
const UtilSymbol_1 = require("./UtilSymbol");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
13
|
+
const http_proxy_agent_1 = __importDefault(require("http-proxy-agent"));
|
|
14
|
+
const https_proxy_agent_1 = __importDefault(require("https-proxy-agent"));
|
|
15
|
+
const AcceptTypeList = ["json", "string"];
|
|
16
|
+
const SendTypeList = ["json", "query", "formData", "none"];
|
|
17
|
+
const SendNoneProc = {
|
|
18
|
+
proc: (opt) => (req) => void req.end()
|
|
17
19
|
};
|
|
18
|
-
const
|
|
20
|
+
const AcceptStringProc = {
|
|
19
21
|
init: '',
|
|
20
22
|
reduce: (acc, dat) => acc + dat,
|
|
21
|
-
parse: (result) =>
|
|
23
|
+
parse: (result) => result
|
|
22
24
|
};
|
|
23
25
|
/**网络请求工具 */
|
|
24
26
|
class UtilCom {
|
|
@@ -30,44 +32,102 @@ class UtilCom {
|
|
|
30
32
|
this._send = _send;
|
|
31
33
|
this._accept = _accept;
|
|
32
34
|
}
|
|
33
|
-
//#region
|
|
35
|
+
//#region 流式创建
|
|
34
36
|
/**设为https请求 */
|
|
35
37
|
static https() {
|
|
36
|
-
return new UtilCom({ protocol: 'https:' },
|
|
38
|
+
return new UtilCom({ protocol: 'https:' }, SendNoneProc, AcceptStringProc);
|
|
37
39
|
}
|
|
38
40
|
/**设为http请求 */
|
|
39
41
|
static http() {
|
|
40
|
-
return new UtilCom({ protocol: 'http:' },
|
|
42
|
+
return new UtilCom({ protocol: 'http:' }, SendNoneProc, AcceptStringProc);
|
|
41
43
|
}
|
|
42
44
|
/**设为get方式的请求 */
|
|
43
45
|
get() {
|
|
44
|
-
|
|
46
|
+
this._data.method = 'GET';
|
|
47
|
+
return this;
|
|
45
48
|
}
|
|
46
49
|
/**设为Post方式的请求 */
|
|
47
50
|
post() {
|
|
48
|
-
|
|
51
|
+
this._data.method = 'POST';
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
/**补充参数
|
|
55
|
+
* 将会替换对应字段, 修改headers请用header函数
|
|
56
|
+
*/
|
|
57
|
+
option(option) {
|
|
58
|
+
this._data = { ...this._data, ...option };
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
/**补充header */
|
|
62
|
+
header(headers) {
|
|
63
|
+
this._data.headers = {
|
|
64
|
+
...this._data.headers,
|
|
65
|
+
...headers,
|
|
66
|
+
};
|
|
67
|
+
return this;
|
|
49
68
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
69
|
+
/**设置agent */
|
|
70
|
+
proxyAgent(url) {
|
|
71
|
+
this._data.agent = UtilFunctions_1.UtilFunc.matchProc(this._data['protocol'], {
|
|
72
|
+
'http:': () => (0, http_proxy_agent_1.default)(url),
|
|
73
|
+
'https:': () => (0, https_proxy_agent_1.default)(url),
|
|
74
|
+
});
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
/**添加一段query */
|
|
78
|
+
query(data) {
|
|
79
|
+
this._data.path = UtilCom.buildQuery(this._data.path ?? '', data);
|
|
80
|
+
return this;
|
|
53
81
|
}
|
|
54
82
|
//#endregion
|
|
55
83
|
//#region 快速预设
|
|
84
|
+
/**收发皆为json的预设 */
|
|
85
|
+
json() {
|
|
86
|
+
return this.sendJson().acceptJson();
|
|
87
|
+
}
|
|
56
88
|
/**收发皆为json的post预设 */
|
|
57
89
|
postJson() {
|
|
58
90
|
return this.post().json();
|
|
59
91
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return this.
|
|
92
|
+
/**无查询参数获取json的get预设 */
|
|
93
|
+
getJson() {
|
|
94
|
+
return this.get().sendNone().acceptJson();
|
|
95
|
+
}
|
|
96
|
+
/**有查询参数获取json的get预设 */
|
|
97
|
+
queryJson() {
|
|
98
|
+
return this.get().sendQuery().acceptJson();
|
|
99
|
+
}
|
|
100
|
+
/**收发皆为json的https-post预设 */
|
|
101
|
+
static httpsPostJson() {
|
|
102
|
+
return UtilCom.https().postJson();
|
|
103
|
+
}
|
|
104
|
+
/**收发皆为json的http-post预设 */
|
|
105
|
+
static httpPostJson() {
|
|
106
|
+
return UtilCom.http().postJson();
|
|
107
|
+
}
|
|
108
|
+
/**无查询参数获取json的https-get预设 */
|
|
109
|
+
static httpsGetJson() {
|
|
110
|
+
return UtilCom.https().getJson();
|
|
111
|
+
}
|
|
112
|
+
/**有查询参数获取json的https-get预设 */
|
|
113
|
+
static httpsQueryJson() {
|
|
114
|
+
return UtilCom.http().queryJson();
|
|
115
|
+
}
|
|
116
|
+
/**无查询参数获取json的http-get预设 */
|
|
117
|
+
static httpGetJson() {
|
|
118
|
+
return UtilCom.http().getJson();
|
|
119
|
+
}
|
|
120
|
+
/**有查询参数获取json的http-get预设 */
|
|
121
|
+
static httpQueryJson() {
|
|
122
|
+
return UtilCom.http().queryJson();
|
|
63
123
|
}
|
|
64
124
|
//#endregion
|
|
65
125
|
//#region 接收数据类型
|
|
66
|
-
|
|
126
|
+
/**预设的接收数据类型*/
|
|
67
127
|
accept(t) {
|
|
68
128
|
const map = {
|
|
69
129
|
'json': this.acceptJson(),
|
|
70
|
-
'
|
|
130
|
+
'string': this.acceptString(),
|
|
71
131
|
};
|
|
72
132
|
return map[t];
|
|
73
133
|
}
|
|
@@ -80,65 +140,52 @@ class UtilCom {
|
|
|
80
140
|
return undefined;
|
|
81
141
|
const { data, ...rest } = result;
|
|
82
142
|
if (data.trim() == "") {
|
|
83
|
-
UtilLogger_1.SLogger.warn(`json accept 接收反馈错误:
|
|
143
|
+
UtilLogger_1.SLogger.warn(`json accept 接收反馈错误: 原始字符串为空`, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
|
|
84
144
|
return { ...result, raw: "", data: null };
|
|
85
145
|
}
|
|
86
146
|
try {
|
|
87
147
|
const obj = JSON.parse(data.trim());
|
|
88
|
-
UtilLogger_1.SLogger.http(`json accept
|
|
148
|
+
UtilLogger_1.SLogger.http(`json accept 接受信息 data:`, UtilFunctions_1.UtilFunc.stringifyJToken(obj, { compress: true, space: 2 }), `result:`, UtilFunctions_1.UtilFunc.stringifyJToken(rest, { compress: true, space: 2 }));
|
|
89
149
|
return { ...rest, data: obj };
|
|
90
150
|
}
|
|
91
151
|
catch (e) {
|
|
92
|
-
UtilLogger_1.SLogger.warn(`json accept 接收反馈错误:${e}
|
|
152
|
+
UtilLogger_1.SLogger.warn(`json accept 接收反馈错误:${e}`, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
|
|
93
153
|
return { ...result, raw: data, data: null };
|
|
94
154
|
}
|
|
95
155
|
}
|
|
96
156
|
};
|
|
97
|
-
|
|
157
|
+
this._accept = proc;
|
|
158
|
+
return this;
|
|
98
159
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const { data, ...rest } = result;
|
|
108
|
-
return data;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
return new UtilCom(this._data, this._send, proc);
|
|
160
|
+
acceptString() {
|
|
161
|
+
this._accept = AcceptStringProc;
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/**自定的接收数据类型*/
|
|
165
|
+
acceptRaw(proc) {
|
|
166
|
+
this._accept = proc;
|
|
167
|
+
return this;
|
|
112
168
|
}
|
|
113
169
|
//#endregion
|
|
114
170
|
//#region 发送数据类型
|
|
115
|
-
|
|
171
|
+
/**预设的发送数据类型*/
|
|
116
172
|
send(t) {
|
|
117
173
|
const map = {
|
|
118
174
|
'json': this.sendJson(),
|
|
119
|
-
|
|
175
|
+
'query': this.sendQuery(),
|
|
176
|
+
'formData': this.sendFormData(),
|
|
177
|
+
'none': this.sendNone(),
|
|
120
178
|
};
|
|
121
179
|
return map[t];
|
|
122
180
|
}
|
|
181
|
+
/**利用 req.write 发送一段json */
|
|
123
182
|
sendJson() {
|
|
124
183
|
const proc = {
|
|
125
184
|
proc: (opt, reqData) => {
|
|
126
185
|
const { method } = opt;
|
|
127
186
|
const isPost = (method == "POST");
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (queryString) {
|
|
131
|
-
// 检查当前路径是否已经包含问号
|
|
132
|
-
const separator = opt?.path?.includes('?') ? '&' : '?';
|
|
133
|
-
opt.path += separator + queryString;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (isPost) {
|
|
137
|
-
this._data.headers ??= {
|
|
138
|
-
'Content-Type': 'application/json',
|
|
139
|
-
'Content-Length': Buffer.from(JSON.stringify(reqData)).length,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
187
|
+
this._data.headers ??= {};
|
|
188
|
+
this._data.headers['Content-Length'] = Buffer.byteLength(JSON.stringify(reqData));
|
|
142
189
|
const procReq = (req) => {
|
|
143
190
|
if (isPost)
|
|
144
191
|
req.write(JSON.stringify(reqData));
|
|
@@ -147,52 +194,83 @@ class UtilCom {
|
|
|
147
194
|
return procReq;
|
|
148
195
|
}
|
|
149
196
|
};
|
|
150
|
-
|
|
197
|
+
this._send = proc;
|
|
198
|
+
this._data.headers ??= {};
|
|
199
|
+
this._data.headers['Content-Type'] = 'application/json';
|
|
200
|
+
return this;
|
|
151
201
|
}
|
|
152
|
-
|
|
202
|
+
/**利用 appendQuery 直接将数据附加在path上发送请求 */
|
|
203
|
+
sendQuery() {
|
|
153
204
|
const proc = {
|
|
154
|
-
proc: (opt) => {
|
|
205
|
+
proc: (opt, reqData) => {
|
|
206
|
+
opt.path = UtilCom.buildQuery(opt.path ?? '', reqData);
|
|
207
|
+
const procReq = (req) => void req.end();
|
|
208
|
+
return procReq;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
this._send = proc;
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
sendFormData() {
|
|
215
|
+
const proc = {
|
|
216
|
+
proc: (opt, formData) => {
|
|
217
|
+
opt.headers = formData.getHeaders();
|
|
155
218
|
const procReq = (req) => {
|
|
219
|
+
formData.pipe(req);
|
|
156
220
|
req.end();
|
|
157
221
|
};
|
|
158
222
|
return procReq;
|
|
159
|
-
}
|
|
223
|
+
},
|
|
160
224
|
};
|
|
161
|
-
|
|
225
|
+
this._send = proc;
|
|
226
|
+
this._data.headers ??= {};
|
|
227
|
+
this._data.headers['Content-Type'] = 'multipart/form-data';
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
sendNone() {
|
|
231
|
+
this._send = SendNoneProc;
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
/**自定的发送数据类型*/
|
|
235
|
+
sendRaw(proc) {
|
|
236
|
+
this._send = proc;
|
|
237
|
+
return this;
|
|
162
238
|
}
|
|
163
239
|
//#endregion
|
|
164
240
|
/**发送请求
|
|
165
|
-
* @param option
|
|
166
|
-
* @param datas
|
|
241
|
+
* @param option - 网络请求选项
|
|
242
|
+
* @param datas - 数据对象
|
|
167
243
|
*/
|
|
168
244
|
async once(option, ...datas) {
|
|
169
245
|
const fullopt = Object.assign({}, this._data, option);
|
|
170
|
-
const
|
|
246
|
+
const proc = await this._send.proc(fullopt, ...datas);
|
|
171
247
|
const { reduce, init, parse } = this._accept;
|
|
172
|
-
const res = await UtilCom.
|
|
248
|
+
const res = await UtilCom.request(fullopt, proc, reduce, init);
|
|
173
249
|
return parse(res);
|
|
174
250
|
}
|
|
175
251
|
/**重复发送网络请求
|
|
176
|
-
* @param option
|
|
177
|
-
* @param
|
|
178
|
-
* @param
|
|
179
|
-
* @param datas
|
|
252
|
+
* @param option - 网络请求选项
|
|
253
|
+
* @param verify - 有效性验证函数
|
|
254
|
+
* @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
|
|
255
|
+
* @param datas - 数据对象
|
|
180
256
|
*/
|
|
181
|
-
async
|
|
182
|
-
|
|
257
|
+
async retry(opt, ...datas) {
|
|
258
|
+
let { option, retries, verify } = opt;
|
|
259
|
+
retries ??= {};
|
|
260
|
+
retries.tryDelay = retries.tryDelay ?? 1000;
|
|
183
261
|
const procFn = () => this.once(option, ...datas);
|
|
184
|
-
return UtilFunctions_1.UtilFunc.
|
|
262
|
+
return UtilFunctions_1.UtilFunc.retryPromise(procFn, verify, retries);
|
|
185
263
|
}
|
|
186
|
-
|
|
187
|
-
* @param
|
|
188
|
-
* @param
|
|
189
|
-
* @param
|
|
190
|
-
* @param
|
|
264
|
+
/**发送网络请求
|
|
265
|
+
* @param option - 网络请求选项
|
|
266
|
+
* @param proc - 请求处理函数 需调用req.end()
|
|
267
|
+
* @param reduce - 数据处理函数
|
|
268
|
+
* @param init - 初始数据
|
|
191
269
|
*/
|
|
192
|
-
static async
|
|
193
|
-
const { protocol, timeout, ...baseReqOpt } =
|
|
270
|
+
static async request(option, proc, reduce, init) {
|
|
271
|
+
const { protocol, timeout, ...baseReqOpt } = option;
|
|
194
272
|
const hasTimeLimit = (timeout ? timeout >= 10_000 : false);
|
|
195
|
-
const flagName = `UtilCom.
|
|
273
|
+
const flagName = `UtilCom.request ${protocol}${baseReqOpt.method} ${UtilFunctions_1.UtilFunc.genUUID()}`;
|
|
196
274
|
let dataPromise = null;
|
|
197
275
|
return new Promise(async (resolve, rejecte) => {
|
|
198
276
|
const resFunc = (res) => {
|
|
@@ -204,10 +282,10 @@ class UtilCom {
|
|
|
204
282
|
resolve(undefined);
|
|
205
283
|
});
|
|
206
284
|
}
|
|
207
|
-
let mergedata =
|
|
285
|
+
let mergedata = init;
|
|
208
286
|
res.setEncoding('utf8');
|
|
209
287
|
res.on('data', chunk => {
|
|
210
|
-
dataPromise = UtilFunctions_1.UtilFunc.queueProc(flagName, async () => mergedata = await
|
|
288
|
+
dataPromise = UtilFunctions_1.UtilFunc.queueProc(flagName, async () => mergedata = await reduce(mergedata, chunk));
|
|
211
289
|
});
|
|
212
290
|
res.on('error', (e) => {
|
|
213
291
|
UtilLogger_1.SLogger.warn(`${flagName} 接收反馈错误:${e}`);
|
|
@@ -243,18 +321,32 @@ class UtilCom {
|
|
|
243
321
|
UtilLogger_1.SLogger.warn(`${flagName} 发送请求错误:${e}`);
|
|
244
322
|
resolve(undefined);
|
|
245
323
|
});
|
|
246
|
-
await
|
|
324
|
+
await proc(req);
|
|
247
325
|
});
|
|
248
326
|
}
|
|
327
|
+
/**构建query */
|
|
328
|
+
static buildQuery(base, data) {
|
|
329
|
+
const queryString = querystring_1.default.stringify(data);
|
|
330
|
+
if (queryString) {
|
|
331
|
+
// 检查当前路径是否已经包含问号
|
|
332
|
+
const separator = base.includes('?') ? '&' : '?';
|
|
333
|
+
base += separator + queryString;
|
|
334
|
+
}
|
|
335
|
+
return base;
|
|
336
|
+
}
|
|
249
337
|
}
|
|
250
338
|
exports.UtilCom = UtilCom;
|
|
251
339
|
if (false)
|
|
252
340
|
((async () => {
|
|
253
|
-
const t = await UtilCom.https().
|
|
254
|
-
.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
341
|
+
const t = await UtilCom.https().postJson()
|
|
342
|
+
.retry({
|
|
343
|
+
option: {
|
|
344
|
+
hostname: 'httpbin.org',
|
|
345
|
+
path: '/post',
|
|
346
|
+
timeout: 10000
|
|
347
|
+
},
|
|
348
|
+
verify: () => UtilSymbol_1.Success,
|
|
349
|
+
retries: {}
|
|
350
|
+
}, { test: 1 });
|
|
259
351
|
console.log(t);
|
|
260
352
|
})());
|
package/dist/UtilFileTools.d.ts
CHANGED
|
@@ -115,7 +115,6 @@ export declare namespace UtilFT {
|
|
|
115
115
|
*/
|
|
116
116
|
function loadJSONFile<T extends JToken>(filePath: string, opt: LoadJsonFileOpt<T>): Promise<T>;
|
|
117
117
|
/**写入JSON文件
|
|
118
|
-
* void (string,Object)
|
|
119
118
|
* @async
|
|
120
119
|
* @param filePath - 文件路径
|
|
121
120
|
* @param token - 所要写入的JToken
|
package/dist/UtilFileTools.js
CHANGED
package/dist/UtilFunctions.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ type StringifyOpt = Partial<{
|
|
|
20
20
|
space: string | number | null | undefined;
|
|
21
21
|
}>;
|
|
22
22
|
/**Promise重试选项 */
|
|
23
|
-
export type
|
|
23
|
+
export type PromiseRetries = Partial<{
|
|
24
24
|
/**重试次数 默认3*/
|
|
25
25
|
count?: number;
|
|
26
26
|
/**尝试间隔时间 超过此事件会重新创建新的Promise
|
|
@@ -29,11 +29,15 @@ export type RepeatPromiseOpt = Partial<{
|
|
|
29
29
|
tryInterval?: number;
|
|
30
30
|
/**尝试延迟 重新尝试时会先等待此毫秒数 毫秒 默认0*/
|
|
31
31
|
tryDelay?: number;
|
|
32
|
+
/**是否使用指数回退 默认false 仅在tryDelay被设置时有效 */
|
|
33
|
+
expBackoff?: boolean;
|
|
34
|
+
/**指数回退上限值 默认无限*/
|
|
35
|
+
expBackoffMax?: number;
|
|
32
36
|
}>;
|
|
33
37
|
type SuccessOut<T> = Outcome<Success, T>;
|
|
34
38
|
type TimeoutOut<T> = Outcome<Timeout, Promise<T>>;
|
|
35
39
|
/**完成的重试请求 */
|
|
36
|
-
export type
|
|
40
|
+
export type PromiseRetryResult<T> = {
|
|
37
41
|
completed: T | undefined;
|
|
38
42
|
/**还未完成的其他Promise 若是验证失败则会返回undefined */
|
|
39
43
|
pending: Promise<T | undefined>[];
|
|
@@ -108,12 +112,12 @@ export declare class UtilFunc {
|
|
|
108
112
|
static getNeverResolvedPromise<T>(): Promise<T>;
|
|
109
113
|
/**重复尝试promise
|
|
110
114
|
* @async
|
|
111
|
-
* @param
|
|
112
|
-
* @param
|
|
113
|
-
* @param
|
|
115
|
+
* @param proc - 发起函数
|
|
116
|
+
* @param verify - 验证函数
|
|
117
|
+
* @param retries - 重试参数 默认 延迟:0ms 间隔:180_000ms 重试:3次
|
|
114
118
|
* @returns 重复结果
|
|
115
119
|
*/
|
|
116
|
-
static
|
|
120
|
+
static retryPromise<T>(proc: () => Promise<T>, verify?: StatusVerifyFn<T>, retries?: PromiseRetries): Promise<PromiseRetryResult<T>>;
|
|
117
121
|
/**创建一个限时的Promise
|
|
118
122
|
* @param func - 处理函数
|
|
119
123
|
* @param timeLimit - 毫秒限时
|
|
@@ -292,7 +296,7 @@ export declare class UtilFunc {
|
|
|
292
296
|
* @param func - 待转换函数
|
|
293
297
|
* @returns 转换完成的函数
|
|
294
298
|
*/
|
|
295
|
-
static eitherize<T extends AnyFunc>(func: T): (...args: Parameters<T>) => Outcome<typeof Success, ReturnType<T>> | Outcome<typeof Failed, Error>;
|
|
299
|
+
static eitherize<T extends AnyFunc>(func: ReturnType<T> extends Promise<any> ? Error & "对异步函数请使用taskEitherize" : T): (...args: Parameters<T>) => Outcome<typeof Success, ReturnType<T>> | Outcome<typeof Failed, Error>;
|
|
296
300
|
/**将传入的异步函数包装为显式处理错误的函数
|
|
297
301
|
* @param func - 待转换函数
|
|
298
302
|
* @returns 转换完成的函数
|
package/dist/UtilFunctions.js
CHANGED
|
@@ -168,35 +168,39 @@ class UtilFunc {
|
|
|
168
168
|
}
|
|
169
169
|
/**重复尝试promise
|
|
170
170
|
* @async
|
|
171
|
-
* @param
|
|
172
|
-
* @param
|
|
173
|
-
* @param
|
|
171
|
+
* @param proc - 发起函数
|
|
172
|
+
* @param verify - 验证函数
|
|
173
|
+
* @param retries - 重试参数 默认 延迟:0ms 间隔:180_000ms 重试:3次
|
|
174
174
|
* @returns 重复结果
|
|
175
175
|
*/
|
|
176
|
-
static async
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const { count, tryInterval } =
|
|
176
|
+
static async retryPromise(proc, verify, retries = {}) {
|
|
177
|
+
retries.count = retries.count ?? 3;
|
|
178
|
+
retries.tryInterval = retries.tryInterval ?? 180_000;
|
|
179
|
+
const { count, tryInterval, tryDelay } = retries;
|
|
180
180
|
/**是否含有超时时间 */
|
|
181
181
|
const hasRepeatTime = (tryInterval >= 5000);
|
|
182
182
|
//验证处理函数
|
|
183
|
-
if (
|
|
184
|
-
|
|
183
|
+
if (verify === undefined)
|
|
184
|
+
verify = () => UtilSymbol_1.Success;
|
|
185
185
|
//进行中的请求
|
|
186
186
|
const plist = [];
|
|
187
187
|
//开始处理
|
|
188
188
|
try {
|
|
189
189
|
//根据最大重试次数限制进行循环
|
|
190
190
|
for (let i = 0; i < count;) {
|
|
191
|
-
if (i > 0 &&
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
if (i > 0 && tryDelay) {
|
|
192
|
+
const delay = retries.expBackoff
|
|
193
|
+
? Math.min((Math.pow(2, i) - 1) * tryDelay, retries.expBackoffMax ?? Infinity)
|
|
194
|
+
: tryDelay;
|
|
195
|
+
await UtilFunc.sleep(delay);
|
|
196
|
+
}
|
|
197
|
+
UtilLogger_1.SLogger.info(`开始第 ${i + 1} 次 retryPromise`);
|
|
194
198
|
//如果 plist 中当前下标的任务还未创建 则 创建当前任务
|
|
195
199
|
if (plist.length < i + 1) {
|
|
196
200
|
plist.push(UtilFunc.timelimitPromise(async () => {
|
|
197
201
|
const index = i;
|
|
198
|
-
const result = await
|
|
199
|
-
const stat = await
|
|
202
|
+
const result = await proc();
|
|
203
|
+
const stat = await verify(result);
|
|
200
204
|
return { result, stat, index };
|
|
201
205
|
}, hasRepeatTime ? tryInterval : undefined));
|
|
202
206
|
}
|
|
@@ -209,7 +213,7 @@ class UtilFunc {
|
|
|
209
213
|
const res = await currObj.result;
|
|
210
214
|
rslove(UtilFunc.outcome(UtilSymbol_1.Success, res));
|
|
211
215
|
});
|
|
212
|
-
UtilLogger_1.SLogger.warn(`第 ${i + 1} 次
|
|
216
|
+
UtilLogger_1.SLogger.warn(`第 ${i + 1} 次 retryPromise 超时 ${tryInterval} ms 开始重试`);
|
|
213
217
|
i++;
|
|
214
218
|
continue;
|
|
215
219
|
}
|
|
@@ -217,14 +221,14 @@ class UtilFunc {
|
|
|
217
221
|
const postresult = currObj.result;
|
|
218
222
|
const result = UtilFunc.matchProc(postresult.stat, {
|
|
219
223
|
[UtilSymbol_1.Success]() {
|
|
220
|
-
UtilLogger_1.SLogger.info(`第 ${postresult.index + 1} 次
|
|
224
|
+
UtilLogger_1.SLogger.info(`第 ${postresult.index + 1} 次 retryPromise 成功`);
|
|
221
225
|
//非当前
|
|
222
226
|
if (postresult.index != i)
|
|
223
227
|
UtilLogger_1.SLogger.info(`成功的 promise 非当前 promise 考虑增大重试时间\n当前index: ${i}\n当前重试时间: ${tryInterval}`);
|
|
224
228
|
return postresult.result;
|
|
225
229
|
},
|
|
226
230
|
[UtilSymbol_1.Terminated]() {
|
|
227
|
-
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次
|
|
231
|
+
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次 retryPromise 终止 停止重试`);
|
|
228
232
|
return postresult.result;
|
|
229
233
|
},
|
|
230
234
|
[UtilSymbol_1.Failed]() {
|
|
@@ -232,12 +236,12 @@ class UtilFunc {
|
|
|
232
236
|
plist[postresult.index] = UtilFunc.getNeverResolvedPromise();
|
|
233
237
|
//是当前
|
|
234
238
|
if (postresult.index == i) {
|
|
235
|
-
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次
|
|
239
|
+
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次 retryPromise 失败 开始重试`);
|
|
236
240
|
i++;
|
|
237
241
|
return UtilSymbol_1.None;
|
|
238
242
|
}
|
|
239
243
|
//非当前
|
|
240
|
-
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次
|
|
244
|
+
UtilLogger_1.SLogger.warn(`第 ${postresult.index + 1} 次 retryPromise 失败`);
|
|
241
245
|
return UtilSymbol_1.None;
|
|
242
246
|
},
|
|
243
247
|
});
|
|
@@ -264,7 +268,7 @@ class UtilFunc {
|
|
|
264
268
|
};
|
|
265
269
|
}
|
|
266
270
|
//全部失败或超时则返回 全pending
|
|
267
|
-
UtilLogger_1.SLogger.warn(`${count} 次
|
|
271
|
+
UtilLogger_1.SLogger.warn(`${count} 次 retryPromise 尝试均失败`);
|
|
268
272
|
return {
|
|
269
273
|
completed: undefined,
|
|
270
274
|
pending: plist
|
|
@@ -286,7 +290,7 @@ class UtilFunc {
|
|
|
286
290
|
};
|
|
287
291
|
}
|
|
288
292
|
catch (err) {
|
|
289
|
-
UtilLogger_1.SLogger.warn(`
|
|
293
|
+
UtilLogger_1.SLogger.warn(`retryPromise 发生意外错误`, err);
|
|
290
294
|
return { completed: undefined, pending: [] };
|
|
291
295
|
}
|
|
292
296
|
}
|
|
@@ -792,8 +796,8 @@ class UtilFunc {
|
|
|
792
796
|
}
|
|
793
797
|
exports.UtilFunc = UtilFunc;
|
|
794
798
|
__decorate([
|
|
795
|
-
(0, UtilDecorators_1.LogTimeAsync)("
|
|
799
|
+
(0, UtilDecorators_1.LogTimeAsync)("retryPromise ", true),
|
|
796
800
|
__metadata("design:type", Function),
|
|
797
801
|
__metadata("design:paramtypes", [Function, Function, Object]),
|
|
798
802
|
__metadata("design:returntype", Promise)
|
|
799
|
-
], UtilFunc, "
|
|
803
|
+
], UtilFunc, "retryPromise", null);
|
package/dist/UtilInterfaces.d.ts
CHANGED
|
@@ -124,7 +124,7 @@ export type RequiredOnly<T> = {
|
|
|
124
124
|
export type WithPrefix<T, P extends string> = {
|
|
125
125
|
[K in (keyof T) as K extends string ? `${P}${K}` : K]: T[K];
|
|
126
126
|
};
|
|
127
|
-
|
|
127
|
+
/**附带状态的返回结果用于状态返回值的封装
|
|
128
128
|
* @template K - 类型键值
|
|
129
129
|
* @template V - 值
|
|
130
130
|
*/
|
|
@@ -134,16 +134,16 @@ export type Outcome<K extends Keyable, V> = {
|
|
|
134
134
|
/**值 */
|
|
135
135
|
readonly result: V;
|
|
136
136
|
};
|
|
137
|
-
|
|
138
|
-
*
|
|
139
|
-
* @template F - 失败时的结果
|
|
137
|
+
/**可进行匹配的对象
|
|
138
|
+
* 如果是Outcome则自动处理status
|
|
140
139
|
*/
|
|
141
|
-
export type Eithercome<S, F> = Outcome<Success, S> | Outcome<Failed, F>;
|
|
142
|
-
/**可进行匹配的 outcome或symbol */
|
|
143
140
|
export type Matchable<T extends Keyable> = T | Outcome<T, unknown>;
|
|
144
141
|
/**可进行匹配的 outcome或symbol 中的状态类型 */
|
|
145
142
|
export type MatchableFlag<T> = T extends infer O | Outcome<infer O, unknown> ? O : never;
|
|
146
|
-
/**从联合 Outcome 中 根据
|
|
143
|
+
/**从联合 Outcome 中 根据 K 提取对应 Outcome
|
|
144
|
+
* @template T - 联合Outcome匹配的类型
|
|
145
|
+
* @template K - 所需的状态
|
|
146
|
+
*/
|
|
147
147
|
export type ExtractOutcome<T, K extends Keyable> = T extends Outcome<infer O, unknown> ? O extends Exclude<O, K> ? never : T : never;
|
|
148
148
|
/**用于辅助解析智能补全的类型
|
|
149
149
|
* 输出schema后替换为 ^.*$ 的 string 匹配
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zwa73/utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.200",
|
|
4
4
|
"description": "my utils",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@deepkit/type": "^1.0.1-alpha.153",
|
|
20
20
|
"fluent-ffmpeg": "2.1.2",
|
|
21
|
+
"form-data": "^4.0.2",
|
|
21
22
|
"glob": "^10.4.1",
|
|
22
23
|
"handlebars": "^4.7.8",
|
|
23
24
|
"html-entities": "^2.3.3",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { regionMacro } from "@zwa73/dev-utils";
|
|
2
|
+
import { dedent } from "./QuickExport";
|
|
3
|
+
|
|
4
|
+
const sep1 = ["http","https"];
|
|
5
|
+
const sep2 = ["get","post"];
|
|
6
|
+
const AcceptTypeList = ["json","raw"]as const;
|
|
7
|
+
const SendTypeList = ["json","query","formData","none","raw"] as const;
|
|
8
|
+
const sep3 = SendTypeList;
|
|
9
|
+
const up = (str:string)=>{
|
|
10
|
+
if (str.length === 0) return str; // 处理空字符串
|
|
11
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
12
|
+
}
|
|
13
|
+
if(false)
|
|
14
|
+
regionMacro("UtilCom宏定义",()=>{
|
|
15
|
+
const result:string[] = [];
|
|
16
|
+
sep1.forEach(s1=>{
|
|
17
|
+
sep2.forEach(s2=>{
|
|
18
|
+
sep3.filter(s=>s!='raw').forEach(s3=>{
|
|
19
|
+
result.push(dedent`
|
|
20
|
+
/** 宏 UtilCom.${s1}().${s2}().send('${s3}').acceptJson() */
|
|
21
|
+
static ${s1}${up(s2)}${up(s3)}(){
|
|
22
|
+
return UtilCom.${s1}().${s2}().send('${s3}' as const).acceptJson();
|
|
23
|
+
}`.trim());
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
return result.reverse().join('\n');
|
|
28
|
+
});
|