@zwa73/utils 1.0.60 → 1.0.62
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/UtilCodecs.d.ts +16 -16
- package/dist/UtilCodecs.js +16 -16
- package/dist/UtilCom.d.ts +22 -25
- package/dist/UtilCom.js +35 -38
- package/dist/UtilDecorators.d.ts +15 -8
- package/dist/UtilDecorators.js +79 -25
- package/dist/UtilFP.d.ts +46 -0
- package/dist/UtilFP.js +52 -0
- package/dist/UtilFfmpegTools.d.ts +30 -30
- package/dist/UtilFfmpegTools.js +32 -32
- package/dist/UtilFileTools.d.ts +30 -35
- package/dist/UtilFileTools.js +17 -18
- package/dist/UtilFunctions.d.ts +37 -78
- package/dist/UtilFunctions.js +27 -62
- package/dist/UtilInterfaces.d.ts +26 -11
- package/dist/UtilInterfaces.js +12 -3
- package/dist/UtilLogger.d.ts +55 -55
- package/dist/UtilLogger.js +55 -55
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/test/composeTest.d.ts +26 -0
- package/dist/test/composeTest.js +50 -0
- package/dist/test/importtest.d.ts +1 -0
- package/dist/test/importtest.js +4 -0
- package/dist/test/test.js +5 -3
- package/package.json +1 -1
- package/src/UtilClass.ts +1051 -1051
- package/src/UtilCodecs.ts +117 -117
- package/src/UtilCom.ts +171 -174
- package/src/UtilDecorators.ts +174 -116
- package/src/UtilFP.ts +98 -0
- package/src/UtilFfmpegTools.ts +271 -271
- package/src/UtilFileTools.ts +231 -236
- package/src/UtilFunctions.ts +289 -364
- package/src/UtilInterfaces.ts +158 -138
- package/src/UtilLogger.ts +386 -386
- package/src/index.ts +10 -9
- package/src/test/composeTest.ts +50 -0
- package/src/test/importtest.ts +5 -0
- package/src/test/test.ts +8 -6
- package/src/test/test2.ts +2 -3
- package/tsconfig.json +2 -7
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,365 +1,290 @@
|
|
|
1
|
-
import * as crypto from "crypto";
|
|
2
|
-
import { ComposedClass, ComposedClassMult,
|
|
3
|
-
import * as cp from "child_process";
|
|
4
|
-
import { SLogger } from "
|
|
5
|
-
|
|
6
|
-
/**常用函数 */
|
|
7
|
-
export namespace UtilFunc{
|
|
8
|
-
/**获取当前时间戳
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
* @param
|
|
19
|
-
* @param
|
|
20
|
-
* @
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
* @
|
|
114
|
-
* @param
|
|
115
|
-
* @
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return currObj.result;
|
|
189
|
-
case "
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
SLogger.warn(
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
let
|
|
248
|
-
let
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**部分类组合
|
|
293
|
-
* 将mixin的部分字段混入base
|
|
294
|
-
* @param base - 基础类
|
|
295
|
-
* @param mixin - 目标类
|
|
296
|
-
* @param fields - 需要混入的字段
|
|
297
|
-
* @returns - 混合完成的类
|
|
298
|
-
*/
|
|
299
|
-
export function composePartClass<Base extends object,Mixin extends object>
|
|
300
|
-
(base:Base,mixin:Mixin,...fields:(keyof Mixin)[]):ComposedPartClass<Base,Mixin,keyof Mixin>{
|
|
301
|
-
const compObj = base as any;
|
|
302
|
-
for(const fd of fields){
|
|
303
|
-
Object.defineProperty(compObj, fd, {
|
|
304
|
-
get: ()=>mixin[fd],
|
|
305
|
-
set: (value)=>{mixin[fd] = value},
|
|
306
|
-
enumerable:true ,
|
|
307
|
-
//writable: true ,
|
|
308
|
-
configurable: true
|
|
309
|
-
});
|
|
310
|
-
//(compObj as any)[fd] = (mixin[fd] as any).bind(mixin);
|
|
311
|
-
}
|
|
312
|
-
return compObj;
|
|
313
|
-
}
|
|
314
|
-
/**类组合
|
|
315
|
-
* 将mixinList每个成员的字段混入base
|
|
316
|
-
* @param base - 基础类
|
|
317
|
-
* @param mixinList - 目标类
|
|
318
|
-
* @returns - 混合完成的类
|
|
319
|
-
*/
|
|
320
|
-
export function composeClass<Base extends object,MixinList extends object[]>
|
|
321
|
-
(base:Base,...mixinList:MixinList):ComposedClassMult<Base,MixinList>{
|
|
322
|
-
let obj = base as any;
|
|
323
|
-
for(let mixin of mixinList as any){
|
|
324
|
-
let propks = Object.getOwnPropertyNames(mixin.constructor.prototype)
|
|
325
|
-
for(const key of propks){
|
|
326
|
-
if(key != "constructor"){
|
|
327
|
-
Object.defineProperty(obj, key, {
|
|
328
|
-
get: ()=>mixin[key],
|
|
329
|
-
set: (value)=>{mixin[key] = value},
|
|
330
|
-
enumerable:true,
|
|
331
|
-
//writable: true,
|
|
332
|
-
configurable: true
|
|
333
|
-
});
|
|
334
|
-
//obj[key] = (mixin as any)[key];
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
for(const key in mixin){
|
|
338
|
-
Object.defineProperty(obj, key, {
|
|
339
|
-
get: ()=>mixin[key],
|
|
340
|
-
set: (value)=>{mixin[key] = value},
|
|
341
|
-
enumerable:true ,
|
|
342
|
-
//writable: true ,
|
|
343
|
-
configurable: true
|
|
344
|
-
});
|
|
345
|
-
//obj[key] = (mixin as any)[key];
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
return obj;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
352
|
-
* @template T - 对象的类型
|
|
353
|
-
* @param obj - 要处理的对象
|
|
354
|
-
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
355
|
-
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
356
|
-
*/
|
|
357
|
-
export function mapObject<T extends Object>
|
|
358
|
-
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
359
|
-
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
360
|
-
result[key as keyof T] = mapper(key as keyof T, value);
|
|
361
|
-
return result;
|
|
362
|
-
}, {} as T);
|
|
363
|
-
}
|
|
364
|
-
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
import { ComposedClass, ComposedClassMult, ComposedClassPart, FuncPropNames, JToken, PromiseProcFn, PromiseStat, PromiseVerifyFn } from "@src/UtilInterfaces";
|
|
3
|
+
import * as cp from "child_process";
|
|
4
|
+
import { SLogger } from "@src/UtilLogger";
|
|
5
|
+
|
|
6
|
+
/**常用函数 */
|
|
7
|
+
export namespace UtilFunc{
|
|
8
|
+
/**获取当前时间戳
|
|
9
|
+
* @returns 时间戳
|
|
10
|
+
*/
|
|
11
|
+
export function getTime(): number {
|
|
12
|
+
return new Date().getTime();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**初始化对象的字段
|
|
16
|
+
* 会改变obj
|
|
17
|
+
* @param obj - 所要初始化的对象
|
|
18
|
+
* @param field - 所要初始化的字段
|
|
19
|
+
* @param defaultVal - 默认值
|
|
20
|
+
* @returns 最终值
|
|
21
|
+
*/
|
|
22
|
+
export function initField<T>(
|
|
23
|
+
obj: Record<string, T>,
|
|
24
|
+
field: string,
|
|
25
|
+
defaultVal: T
|
|
26
|
+
): T {
|
|
27
|
+
if (!(field in obj)) obj[field] = defaultVal;
|
|
28
|
+
return obj[field];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**生成一串uuid
|
|
32
|
+
* @returns uuid
|
|
33
|
+
*/
|
|
34
|
+
export function genUUID() {
|
|
35
|
+
return crypto.randomBytes(16).toString("hex");
|
|
36
|
+
}
|
|
37
|
+
/**计算Hash
|
|
38
|
+
* @param str - 待计算的字符串
|
|
39
|
+
* @returns hash
|
|
40
|
+
*/
|
|
41
|
+
export function calcHash(str:string) {
|
|
42
|
+
return crypto.createHash('md5').update(str).digest('hex');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**深克隆 序列化并反序列化
|
|
46
|
+
* @template T - JToken类型的泛型
|
|
47
|
+
* @param obj - 克隆目标
|
|
48
|
+
* @returns 克隆结果
|
|
49
|
+
*/
|
|
50
|
+
export function deepClone<T extends JToken>(obj: T): T {
|
|
51
|
+
return JSON.parse(JSON.stringify(obj));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**是否为安全的数字
|
|
55
|
+
* @param num - 所要检测的数字
|
|
56
|
+
* @returns 是否安全
|
|
57
|
+
*/
|
|
58
|
+
export function isSafeNumber(num: number): boolean {
|
|
59
|
+
if (num === undefined || num == null || isNaN(num)) return false;
|
|
60
|
+
if(typeof num === 'number') return true;
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**等待 timeMs 毫秒
|
|
65
|
+
* @async
|
|
66
|
+
* @param timeMs - 等待的毫秒数
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
export async function sleep(timeMs: number): Promise<boolean> {
|
|
70
|
+
return new Promise(function (resolve, rejecte) {
|
|
71
|
+
let timer = setTimeout(function () {
|
|
72
|
+
resolve(true);
|
|
73
|
+
}, timeMs);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**封装的 cp.exec 执行一段指令 指令完成后返回 Promise
|
|
78
|
+
* @param command 指令文本
|
|
79
|
+
*/
|
|
80
|
+
export function exec(command: string) {
|
|
81
|
+
return new Promise<{ stdout:string, stderr:string }>
|
|
82
|
+
((resolve, reject) => {
|
|
83
|
+
cp.exec(command, (error, stdout, stderr) => {
|
|
84
|
+
if (error)
|
|
85
|
+
reject(error);
|
|
86
|
+
else
|
|
87
|
+
resolve({ stdout, stderr });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**永不完成的Promise单例 */
|
|
93
|
+
const NeverResolvedPromise = new Promise(()=>{});
|
|
94
|
+
/**获得一个永不完成的Promise单例 */
|
|
95
|
+
export function getNeverResolvedPromise<T>():Promise<T>{
|
|
96
|
+
return NeverResolvedPromise as Promise<T>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**进行中的请求 */
|
|
100
|
+
type ProcessingPromise<T> = {
|
|
101
|
+
/**主体请求 */
|
|
102
|
+
result:T;
|
|
103
|
+
/**请求状态 */
|
|
104
|
+
stat:PromiseStat|Promise<PromiseStat>;
|
|
105
|
+
/**请求下标/序号 */
|
|
106
|
+
index:number;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**重复尝试promise
|
|
110
|
+
* @async
|
|
111
|
+
* @param procFn - 发起函数
|
|
112
|
+
* @param verifyFn - 验证函数
|
|
113
|
+
* @param repeatCount - 重试次数
|
|
114
|
+
* @param repeatTime - 超时时间/秒 最小为10秒
|
|
115
|
+
* @returns - 结果 null 为全部失败/超时
|
|
116
|
+
*/
|
|
117
|
+
export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:PromiseVerifyFn<T>,
|
|
118
|
+
repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
|
|
119
|
+
|
|
120
|
+
//计时
|
|
121
|
+
const timeflag = "repeatPromise "+UtilFunc.genUUID();
|
|
122
|
+
SLogger.time(timeflag);
|
|
123
|
+
|
|
124
|
+
//转换为毫秒
|
|
125
|
+
const hasRepeatTime = (repeatTime>=10);
|
|
126
|
+
if(hasRepeatTime) repeatTime*=1000;
|
|
127
|
+
|
|
128
|
+
//验证处理函数
|
|
129
|
+
if(verifyFn===undefined)
|
|
130
|
+
verifyFn = ()=>"Completed";
|
|
131
|
+
|
|
132
|
+
//计时器
|
|
133
|
+
let timer:NodeJS.Timer|null = null;
|
|
134
|
+
let timerP:Promise<"Timeout">|null=null;
|
|
135
|
+
let resolveFn:((value: "Timeout" | PromiseLike<"Timeout">)=>void)|null = null;
|
|
136
|
+
/**清理计时器 */
|
|
137
|
+
const clearTimer = ()=>{
|
|
138
|
+
if(timer!=null)
|
|
139
|
+
clearInterval(timer);
|
|
140
|
+
if(resolveFn!=null)
|
|
141
|
+
resolveFn("Timeout");
|
|
142
|
+
timerP=null;
|
|
143
|
+
timer=null;
|
|
144
|
+
resolveFn=null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//进行中的请求
|
|
148
|
+
const plist:Promise<ProcessingPromise<T>>[] = [];
|
|
149
|
+
|
|
150
|
+
//开始处理
|
|
151
|
+
try{
|
|
152
|
+
for(let i=0;i<repeatCount;){
|
|
153
|
+
SLogger.info(`开始第 ${i+1} 次 repeatPromise`);
|
|
154
|
+
//创建当前任务
|
|
155
|
+
if(plist.length<i+1){
|
|
156
|
+
plist.push(procFn().then(result =>
|
|
157
|
+
({result, stat:verifyFn!(result), index:i})));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
//创建定时器
|
|
161
|
+
if(timerP==null){
|
|
162
|
+
timerP = new Promise<"Timeout">(function(resolve, rejecte){
|
|
163
|
+
resolveFn = resolve;
|
|
164
|
+
timer = setTimeout(()=>resolve("Timeout"),
|
|
165
|
+
hasRepeatTime? repeatTime:Infinity);//无限制则无限时间
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//等待完成
|
|
170
|
+
const currObj = await Promise.race([...plist, timerP]);
|
|
171
|
+
|
|
172
|
+
//超时处理
|
|
173
|
+
if(currObj=="Timeout"){
|
|
174
|
+
SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
175
|
+
clearTimer(); i++;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const poststat = await currObj.stat;
|
|
179
|
+
switch(poststat){
|
|
180
|
+
case "Completed"://完成
|
|
181
|
+
SLogger.info(`第 ${currObj.index+1} 次 repeatPromise 成功`);
|
|
182
|
+
//非当前
|
|
183
|
+
if(currObj.index!=i)
|
|
184
|
+
SLogger.info(`成功的 promise 非当前 promise 考虑增大重试间隔\n当前index: ${i}\n当前间隔: ${repeatTime}`);
|
|
185
|
+
return currObj.result;
|
|
186
|
+
case "Terminated"://终止
|
|
187
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 终止 停止重试`);
|
|
188
|
+
return currObj.result;
|
|
189
|
+
case "Failed"://验证失败
|
|
190
|
+
//抛弃失败
|
|
191
|
+
plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
|
|
192
|
+
//是当前
|
|
193
|
+
if(currObj.index==i){
|
|
194
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败 开始重试`);
|
|
195
|
+
clearTimer(); i++;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
//非当前
|
|
199
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//全部失败或超时则返回null
|
|
204
|
+
SLogger.warn(`${repeatCount} 次 repeatPromise 尝试均失败`);
|
|
205
|
+
return null;
|
|
206
|
+
}catch(err){
|
|
207
|
+
SLogger.warn(`repeatPromise 发生错误`,err);
|
|
208
|
+
return null;
|
|
209
|
+
}finally{
|
|
210
|
+
//清理
|
|
211
|
+
clearTimer();
|
|
212
|
+
SLogger.timeEnd(timeflag);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**部分类组合
|
|
217
|
+
* 将mixin的部分字段混入base
|
|
218
|
+
* @param base - 基础类
|
|
219
|
+
* @param mixin - 目标类
|
|
220
|
+
* @param fields - 需要混入的字段
|
|
221
|
+
* @returns 混合完成的类
|
|
222
|
+
*/
|
|
223
|
+
export function composeClassPart
|
|
224
|
+
<Base extends object,Mixin extends object,Field extends keyof Mixin>
|
|
225
|
+
(base:Base,mixin:Mixin,...fields:Field[]):ComposedClassPart<Base,Mixin,Field>{
|
|
226
|
+
const compObj = base as any;
|
|
227
|
+
for(const fd of fields){
|
|
228
|
+
Object.defineProperty(compObj, fd, {
|
|
229
|
+
get: ()=>mixin[fd],
|
|
230
|
+
set: (value)=>{mixin[fd] = value},
|
|
231
|
+
enumerable:true ,
|
|
232
|
+
//writable: true ,
|
|
233
|
+
configurable: true
|
|
234
|
+
});
|
|
235
|
+
//(compObj as any)[fd] = (mixin[fd] as any).bind(mixin);
|
|
236
|
+
}
|
|
237
|
+
return compObj;
|
|
238
|
+
}
|
|
239
|
+
/**类组合
|
|
240
|
+
* 将mixinList每个成员的字段混入base
|
|
241
|
+
* @param base - 基础类
|
|
242
|
+
* @param mixinList - 目标类
|
|
243
|
+
* @returns - 混合完成的类
|
|
244
|
+
*/
|
|
245
|
+
export function composeClass<Base extends object,MixinList extends object[]>
|
|
246
|
+
(base:Base,...mixinList:MixinList):ComposedClassMult<Base,MixinList>{
|
|
247
|
+
let obj = base as any;
|
|
248
|
+
for(let mixin of mixinList as any){
|
|
249
|
+
let propks = Object.getOwnPropertyNames(mixin.constructor.prototype)
|
|
250
|
+
for(const key of propks){
|
|
251
|
+
if(key != "constructor"){
|
|
252
|
+
Object.defineProperty(obj, key, {
|
|
253
|
+
get: ()=>mixin[key],
|
|
254
|
+
set: (value)=>{mixin[key] = value},
|
|
255
|
+
enumerable:true,
|
|
256
|
+
//writable: true,
|
|
257
|
+
configurable: true
|
|
258
|
+
});
|
|
259
|
+
//obj[key] = (mixin as any)[key];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for(const key in mixin){
|
|
263
|
+
Object.defineProperty(obj, key, {
|
|
264
|
+
get: ()=>mixin[key],
|
|
265
|
+
set: (value)=>{mixin[key] = value},
|
|
266
|
+
enumerable:true ,
|
|
267
|
+
//writable: true ,
|
|
268
|
+
configurable: true
|
|
269
|
+
});
|
|
270
|
+
//obj[key] = (mixin as any)[key];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return obj;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
277
|
+
* @template T - 对象的类型
|
|
278
|
+
* @param obj - 要处理的对象
|
|
279
|
+
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
280
|
+
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
281
|
+
*/
|
|
282
|
+
export function mapEntries<T extends Object>
|
|
283
|
+
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
284
|
+
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
285
|
+
result[key as keyof T] = mapper(key as keyof T, value);
|
|
286
|
+
return result;
|
|
287
|
+
}, {} as T);
|
|
288
|
+
}
|
|
289
|
+
|
|
365
290
|
}
|