@zwa73/utils 1.0.76 → 1.0.78
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/QuickFunction.d.ts +15 -0
- package/dist/QuickFunction.js +27 -0
- package/dist/UtilCom.js +2 -3
- package/dist/UtilDecorators.d.ts +10 -0
- package/dist/UtilDecorators.js +40 -3
- package/dist/UtilFP.js +2 -0
- package/dist/UtilFileTools.js +2 -2
- package/dist/UtilFunctions.d.ts +40 -17
- package/dist/UtilFunctions.js +119 -96
- package/dist/UtilInterfaces.d.ts +43 -13
- package/dist/UtilInterfaces.js +0 -12
- package/dist/UtilSymbol.d.ts +15 -0
- package/dist/UtilSymbol.js +13 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
- package/src/QuickFunction.ts +36 -0
- package/src/UtilCom.ts +3 -3
- package/src/UtilDecorators.ts +37 -1
- package/src/UtilFP.ts +5 -0
- package/src/UtilFileTools.ts +3 -2
- package/src/UtilFunctions.ts +143 -91
- package/src/UtilInterfaces.ts +57 -17
- package/src/UtilSymbol.ts +15 -0
- package/src/index.ts +3 -1
- package/src/test/composeTest.ts +28 -1
package/src/UtilFP.ts
CHANGED
|
@@ -29,11 +29,13 @@ export function curry<T extends Function>(fn: T): CurryFunc<T> {
|
|
|
29
29
|
/**可组合的函数 */
|
|
30
30
|
type CompFunc<T, R> = (arg: T) => R;
|
|
31
31
|
|
|
32
|
+
|
|
32
33
|
/**函数管道组合
|
|
33
34
|
* 从左到右执行
|
|
34
35
|
* @param fs - 待组合的函数
|
|
35
36
|
* @returns 组合完成的函数
|
|
36
37
|
*/
|
|
38
|
+
//#region flow重载
|
|
37
39
|
export function flow<I>(...fs: CompFunc<I, I>[]): CompFunc<I, I>;
|
|
38
40
|
export function flow<I, R1>(f1: CompFunc<I, R1>,...fs: CompFunc<R1, R1>[]): CompFunc<I, R1>;
|
|
39
41
|
export function flow<I, R1, R2>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>,...fs: CompFunc<R2, R2>[]): CompFunc<I, R2>;
|
|
@@ -44,6 +46,7 @@ export function flow<I, R1, R2, R3, R4, R5, R6>(f1: CompFunc<I, R1>, f2: CompFun
|
|
|
44
46
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>,...fs: CompFunc<R7, R7>[]): CompFunc<I, R7>;
|
|
45
47
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7, R8>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>,...fs: CompFunc<R8, R8>[]): CompFunc<I, R8>;
|
|
46
48
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7, R8, R9>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>, f9: CompFunc<R8, R9>,...fs: CompFunc<R9, R9>[]): CompFunc<I, R9>;
|
|
49
|
+
//#endregion
|
|
47
50
|
export function flow<T>(...fs: ((arg: T) => T)[]): (arg: T) => T {
|
|
48
51
|
return (arg: T): T => {
|
|
49
52
|
return fs.reduce((value, func) => func(value), arg);
|
|
@@ -56,6 +59,7 @@ export function flow<T>(...fs: ((arg: T) => T)[]): (arg: T) => T {
|
|
|
56
59
|
* @param fs - 待组合的函数
|
|
57
60
|
* @returns 经过所有函数处理后的结果
|
|
58
61
|
*/
|
|
62
|
+
//#region pipe重载
|
|
59
63
|
export function pipe<I>(input: I, ...fs: CompFunc<I, I>[]): I;
|
|
60
64
|
export function pipe<I, R1>(input: I, f1: CompFunc<I, R1>,...fs: CompFunc<R1, R1>[]): R1;
|
|
61
65
|
export function pipe<I, R1, R2>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>,...fs: CompFunc<R2, R2>[]): R2;
|
|
@@ -66,6 +70,7 @@ export function pipe<I, R1, R2, R3, R4, R5, R6>(input: I, f1: CompFunc<I, R1>, f
|
|
|
66
70
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>,...fs: CompFunc<R7, R7>[]): R7;
|
|
67
71
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7, R8>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>,...fs: CompFunc<R8, R8>[]): R8;
|
|
68
72
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7, R8, R9>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>, f9: CompFunc<R8, R9>,...fs: CompFunc<R9, R9>[]): R9;
|
|
73
|
+
//#endregion
|
|
69
74
|
export function pipe<T>(input: T, ...fs: ((arg: T) => T)[]): T {
|
|
70
75
|
return fs.reduce((value, func) => func(value), input);
|
|
71
76
|
}
|
package/src/UtilFileTools.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
-
import { JToken
|
|
3
|
+
import { JToken } from "@src/UtilInterfaces";
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
5
|
import * as JSON5 from 'json5';
|
|
6
6
|
import { globSync } from "glob";
|
|
7
|
+
import { UtilFunc } from "./UtilFunctions";
|
|
7
8
|
|
|
8
9
|
/**文件工具 */
|
|
9
10
|
export namespace UtilFT{
|
|
@@ -178,7 +179,7 @@ export async function writeJSONFile(
|
|
|
178
179
|
filePath: string,
|
|
179
180
|
token: JToken
|
|
180
181
|
): Promise<void> {
|
|
181
|
-
let str = stringifyJToken(token);
|
|
182
|
+
let str = UtilFunc.stringifyJToken(token);
|
|
182
183
|
if (path.extname(filePath) !== '.json') filePath += '.json';
|
|
183
184
|
|
|
184
185
|
// 判断文件路径是否存在 不存在则创建
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import { ComposedClass, ComposedMixinable,
|
|
2
|
+
import { ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Mixinable, Outcome, PromiseStat, PromiseVerifyFn } from "@src/UtilInterfaces";
|
|
3
3
|
import * as cp from "child_process";
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
|
+
import { Completed, Failed, None, Terminated, Timeout } from "./UtilSymbol";
|
|
6
|
+
import { match, outcome } from "./QuickFunction";
|
|
7
|
+
import { LogTimeAsync } from "./UtilDecorators";
|
|
5
8
|
|
|
9
|
+
|
|
10
|
+
type CompleteCome<T> = Outcome<Completed,T>;
|
|
11
|
+
type TimeoutCome<T> = Outcome<Timeout,Promise<T>>;
|
|
12
|
+
/**永不完成的Promise单例 */
|
|
13
|
+
const NeverResolvedPromise = new Promise(()=>{});
|
|
14
|
+
/**进行中的请求 */
|
|
15
|
+
type ProcessingPromise<T> = {
|
|
16
|
+
/**主体请求 */
|
|
17
|
+
result:T;
|
|
18
|
+
/**请求状态 */
|
|
19
|
+
stat:PromiseStat;
|
|
20
|
+
/**请求下标/序号 */
|
|
21
|
+
index:number;
|
|
22
|
+
};
|
|
6
23
|
/**常用函数 */
|
|
7
|
-
export
|
|
24
|
+
export class UtilFunc{
|
|
8
25
|
/**获取当前时间戳
|
|
9
26
|
* @returns 时间戳
|
|
10
27
|
*/
|
|
11
|
-
|
|
28
|
+
static getTime(): number {
|
|
12
29
|
return new Date().getTime();
|
|
13
30
|
}
|
|
14
31
|
|
|
@@ -19,7 +36,7 @@ export function getTime(): number {
|
|
|
19
36
|
* @param defaultVal - 默认值
|
|
20
37
|
* @returns 最终值
|
|
21
38
|
*/
|
|
22
|
-
|
|
39
|
+
static initField<T extends object,K extends keyof T>(
|
|
23
40
|
obj: T,
|
|
24
41
|
field: K,
|
|
25
42
|
defaultVal: T[K]
|
|
@@ -33,7 +50,7 @@ export function initField<T extends object,K extends keyof T>(
|
|
|
33
50
|
* @param checkObj - 用于检测的对象 在对应key缺失时赋予对应值 如果值为函数, 则赋予执行结果 如果结果为 undefined 则不赋值
|
|
34
51
|
* @returns 完成初始化的对象
|
|
35
52
|
*/
|
|
36
|
-
|
|
53
|
+
static initObject<T extends JObject>
|
|
37
54
|
(obj:T,checkObj:{[P in keyof T]:T[P]|(()=>void|T[P])}){
|
|
38
55
|
const fixobj = obj as any;
|
|
39
56
|
for(const key in checkObj){
|
|
@@ -52,14 +69,14 @@ export function initObject<T extends JObject>
|
|
|
52
69
|
/**生成一串uuid
|
|
53
70
|
* @returns uuid
|
|
54
71
|
*/
|
|
55
|
-
|
|
72
|
+
static genUUID() {
|
|
56
73
|
return crypto.randomBytes(16).toString("hex");
|
|
57
74
|
}
|
|
58
75
|
/**计算Hash
|
|
59
76
|
* @param str - 待计算的字符串
|
|
60
77
|
* @returns hash
|
|
61
78
|
*/
|
|
62
|
-
|
|
79
|
+
static calcHash(str:string) {
|
|
63
80
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
64
81
|
}
|
|
65
82
|
|
|
@@ -68,7 +85,7 @@ export function calcHash(str:string) {
|
|
|
68
85
|
* @param obj - 克隆目标
|
|
69
86
|
* @returns 克隆结果
|
|
70
87
|
*/
|
|
71
|
-
|
|
88
|
+
static deepClone<T extends JToken>(obj: T): T {
|
|
72
89
|
return JSON.parse(JSON.stringify(obj));
|
|
73
90
|
}
|
|
74
91
|
|
|
@@ -76,7 +93,7 @@ export function deepClone<T extends JToken>(obj: T): T {
|
|
|
76
93
|
* @param num - 所要检测的数字
|
|
77
94
|
* @returns 是否安全
|
|
78
95
|
*/
|
|
79
|
-
|
|
96
|
+
static isSafeNumber(num: number): boolean {
|
|
80
97
|
if (num === undefined || num == null || isNaN(num)) return false;
|
|
81
98
|
if(typeof num === 'number') return true;
|
|
82
99
|
return false;
|
|
@@ -87,10 +104,18 @@ export function isSafeNumber(num: number): boolean {
|
|
|
87
104
|
* @param timeMs - 等待的毫秒数
|
|
88
105
|
* @returns
|
|
89
106
|
*/
|
|
90
|
-
|
|
107
|
+
static async sleep<T>(timeMs: number): Promise<void>
|
|
108
|
+
/**等待 timeMs 毫秒
|
|
109
|
+
* @async
|
|
110
|
+
* @param timeMs - 等待的毫秒数
|
|
111
|
+
* @param result - 结果
|
|
112
|
+
* @returns
|
|
113
|
+
*/
|
|
114
|
+
static async sleep<T>(timeMs: number, result:T): Promise<T>
|
|
115
|
+
static async sleep<T>(timeMs: number, result?:T): Promise<T|undefined> {
|
|
91
116
|
return new Promise(function (resolve, rejecte) {
|
|
92
117
|
let timer = setTimeout(function () {
|
|
93
|
-
resolve(
|
|
118
|
+
resolve(result);
|
|
94
119
|
}, timeMs);
|
|
95
120
|
});
|
|
96
121
|
}
|
|
@@ -98,7 +123,7 @@ export async function sleep(timeMs: number): Promise<boolean> {
|
|
|
98
123
|
/**封装的 cp.exec 执行一段指令 指令完成后返回 Promise
|
|
99
124
|
* @param command 指令文本
|
|
100
125
|
*/
|
|
101
|
-
|
|
126
|
+
static exec(command: string) {
|
|
102
127
|
return new Promise<{ stdout:string, stderr:string }>
|
|
103
128
|
((resolve, reject) => {
|
|
104
129
|
cp.exec(command, (error, stdout, stderr) => {
|
|
@@ -110,116 +135,98 @@ export function exec(command: string) {
|
|
|
110
135
|
});
|
|
111
136
|
}
|
|
112
137
|
|
|
113
|
-
|
|
114
|
-
const NeverResolvedPromise = new Promise(()=>{});
|
|
138
|
+
|
|
115
139
|
/**获得一个永不完成的Promise单例 */
|
|
116
|
-
|
|
140
|
+
static getNeverResolvedPromise<T>():Promise<T>{
|
|
117
141
|
return NeverResolvedPromise as Promise<T>;
|
|
118
142
|
}
|
|
119
143
|
|
|
120
|
-
/**进行中的请求 */
|
|
121
|
-
type ProcessingPromise<T> = {
|
|
122
|
-
/**主体请求 */
|
|
123
|
-
result:T;
|
|
124
|
-
/**请求状态 */
|
|
125
|
-
stat:PromiseStat|Promise<PromiseStat>;
|
|
126
|
-
/**请求下标/序号 */
|
|
127
|
-
index:number;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
144
|
/**重复尝试promise
|
|
131
145
|
* @async
|
|
132
146
|
* @param procFn - 发起函数
|
|
133
147
|
* @param verifyFn - 验证函数
|
|
134
148
|
* @param repeatCount - 重试次数
|
|
135
149
|
* @param repeatTime - 超时时间/秒 最小为10秒
|
|
136
|
-
* @returns
|
|
150
|
+
* @returns 结果 null 为全部失败/超时
|
|
137
151
|
*/
|
|
138
|
-
|
|
152
|
+
@LogTimeAsync("repeatPromise ",true)
|
|
153
|
+
static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>,
|
|
139
154
|
repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
const timeflag = "repeatPromise "+UtilFunc.genUUID();
|
|
143
|
-
SLogger.time(timeflag);
|
|
144
|
-
|
|
145
|
-
//转换为毫秒
|
|
156
|
+
/**是否含有超时时间 */
|
|
146
157
|
const hasRepeatTime = (repeatTime>=10);
|
|
158
|
+
//转换为毫秒
|
|
147
159
|
if(hasRepeatTime) repeatTime*=1000;
|
|
148
160
|
|
|
149
161
|
//验证处理函数
|
|
150
162
|
if(verifyFn===undefined)
|
|
151
|
-
verifyFn = ()=>
|
|
152
|
-
|
|
153
|
-
//计时器
|
|
154
|
-
let timer:NodeJS.Timer|null = null;
|
|
155
|
-
let timerP:Promise<"Timeout">|null=null;
|
|
156
|
-
let resolveFn:((value: "Timeout" | PromiseLike<"Timeout">)=>void)|null = null;
|
|
157
|
-
/**清理计时器 */
|
|
158
|
-
const clearTimer = ()=>{
|
|
159
|
-
if(timer!=null)
|
|
160
|
-
clearInterval(timer);
|
|
161
|
-
if(resolveFn!=null)
|
|
162
|
-
resolveFn("Timeout");
|
|
163
|
-
timerP=null;
|
|
164
|
-
timer=null;
|
|
165
|
-
resolveFn=null;
|
|
166
|
-
}
|
|
163
|
+
verifyFn = ()=>Completed;
|
|
167
164
|
|
|
168
165
|
//进行中的请求
|
|
169
|
-
const plist:Promise<
|
|
166
|
+
const plist:Promise<
|
|
167
|
+
CompleteCome<ProcessingPromise<T>>|
|
|
168
|
+
TimeoutCome<ProcessingPromise<T>>
|
|
169
|
+
>[] = [];
|
|
170
170
|
|
|
171
171
|
//开始处理
|
|
172
172
|
try{
|
|
173
|
+
//根据最大重试次数限制进行循环
|
|
173
174
|
for(let i=0;i<repeatCount;){
|
|
174
175
|
SLogger.info(`开始第 ${i+1} 次 repeatPromise`);
|
|
175
|
-
//创建当前任务
|
|
176
|
-
if(plist.length<i+1){
|
|
177
|
-
plist.push(procFn().then(result =>
|
|
178
|
-
({result, stat:verifyFn!(result), index:i})));
|
|
179
|
-
}
|
|
180
176
|
|
|
181
|
-
|
|
182
|
-
if(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
})
|
|
177
|
+
//如果 plist 中当前下标的任务还未创建 则 创建当前任务
|
|
178
|
+
if(plist.length<i+1){
|
|
179
|
+
plist.push(UtilFunc.timelimitPromise<ProcessingPromise<T>>(async ()=>{
|
|
180
|
+
const result = await procFn();
|
|
181
|
+
const stat = await verifyFn!(result);
|
|
182
|
+
return {result, stat, index:i}
|
|
183
|
+
}));
|
|
188
184
|
}
|
|
189
185
|
|
|
190
|
-
|
|
191
|
-
const currObj = await Promise.race([...plist
|
|
186
|
+
//等待任意任务 或当前计时器完成
|
|
187
|
+
const currObj = await Promise.race([...plist]);
|
|
192
188
|
|
|
193
189
|
//超时处理
|
|
194
|
-
if(currObj
|
|
190
|
+
if(currObj.status===Timeout){
|
|
191
|
+
//解除timeout替换原参数
|
|
192
|
+
plist[i]=new Promise(async (rslove)=>{
|
|
193
|
+
const res = await currObj.result;
|
|
194
|
+
rslove(outcome(Completed,res));
|
|
195
|
+
})
|
|
195
196
|
SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
196
|
-
|
|
197
|
+
i++;
|
|
197
198
|
continue;
|
|
198
199
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
|
|
201
|
+
//路由请求状态
|
|
202
|
+
const postresult = currObj.result;
|
|
203
|
+
const result = match(postresult.stat,{
|
|
204
|
+
[Completed](){
|
|
205
|
+
SLogger.info(`第 ${postresult.index+1} 次 repeatPromise 成功`);
|
|
203
206
|
//非当前
|
|
204
|
-
if(
|
|
207
|
+
if(postresult.index!=i)
|
|
205
208
|
SLogger.info(`成功的 promise 非当前 promise 考虑增大重试间隔\n当前index: ${i}\n当前间隔: ${repeatTime}`);
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
return postresult.result;
|
|
210
|
+
},
|
|
211
|
+
[Terminated](){
|
|
212
|
+
SLogger.warn(`第 ${postresult.index+1} 次 repeatPromise 终止 停止重试`);
|
|
213
|
+
return postresult.result;
|
|
214
|
+
},
|
|
215
|
+
[Failed]():None{
|
|
211
216
|
//抛弃失败
|
|
212
|
-
plist[
|
|
217
|
+
plist[postresult.index] = UtilFunc.getNeverResolvedPromise();
|
|
213
218
|
//是当前
|
|
214
|
-
if(
|
|
215
|
-
SLogger.warn(`第 ${
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
if(postresult.index==i){
|
|
220
|
+
SLogger.warn(`第 ${postresult.index+1} 次 repeatPromise 失败 开始重试`);
|
|
221
|
+
i++;
|
|
222
|
+
return None;
|
|
218
223
|
}
|
|
219
224
|
//非当前
|
|
220
|
-
SLogger.warn(`第 ${
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
SLogger.warn(`第 ${postresult.index+1} 次 repeatPromise 失败`);
|
|
226
|
+
return None;
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
if(result !== None) return result;
|
|
223
230
|
}
|
|
224
231
|
//全部失败或超时则返回null
|
|
225
232
|
SLogger.warn(`${repeatCount} 次 repeatPromise 尝试均失败`);
|
|
@@ -227,13 +234,47 @@ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:Promise
|
|
|
227
234
|
}catch(err){
|
|
228
235
|
SLogger.warn(`repeatPromise 发生错误`,err);
|
|
229
236
|
return null;
|
|
230
|
-
}finally{
|
|
231
|
-
//清理
|
|
232
|
-
clearTimer();
|
|
233
|
-
SLogger.timeEnd(timeflag);
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
239
|
|
|
240
|
+
|
|
241
|
+
/**创建一个限时的Promise
|
|
242
|
+
* @param func - 处理函数
|
|
243
|
+
* @param timeLimit - 毫秒限时
|
|
244
|
+
* @returns 超时则返回 处理函数委托 完成则返回结果
|
|
245
|
+
*/
|
|
246
|
+
static timelimitPromise<T>
|
|
247
|
+
(func:()=>Promise<T>|T,timeLimit?:number):Promise<CompleteCome<T>|TimeoutCome<T>>{
|
|
248
|
+
return new Promise<CompleteCome<T>|TimeoutCome<T>>((reslove)=>{
|
|
249
|
+
let clearTimer:(()=>void)| null = null;
|
|
250
|
+
let proc = (async ()=>await func())();
|
|
251
|
+
|
|
252
|
+
const procerP = new Promise<CompleteCome<T>>(async (resolve)=>{
|
|
253
|
+
const res = await proc;
|
|
254
|
+
if(clearTimer) clearTimer();
|
|
255
|
+
resolve(outcome(Completed,res))
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const timerP = timeLimit
|
|
259
|
+
? new Promise<TimeoutCome<T>>((resolve)=>{
|
|
260
|
+
const timer = setTimeout(()=>
|
|
261
|
+
resolve(outcome(Timeout,proc))
|
|
262
|
+
,timeLimit);//无限制则无限时间
|
|
263
|
+
|
|
264
|
+
clearTimer = ()=>{
|
|
265
|
+
resolve(outcome(Timeout,proc))
|
|
266
|
+
clearInterval(timer)
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
: UtilFunc.getNeverResolvedPromise<TimeoutCome<T>>();
|
|
270
|
+
|
|
271
|
+
const result = Promise.race([procerP,timerP]);
|
|
272
|
+
reslove(result);
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
237
278
|
/**部分类组合
|
|
238
279
|
* 将mixin的部分字段混入base
|
|
239
280
|
* @param base - 基础类
|
|
@@ -242,7 +283,7 @@ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:Promise
|
|
|
242
283
|
* @param fields - 需要混入的字段
|
|
243
284
|
* @returns 混合完成的类
|
|
244
285
|
*/
|
|
245
|
-
|
|
286
|
+
static composeClassPart
|
|
246
287
|
<Base extends object,Mixin extends object,Field extends keyof Mixin>
|
|
247
288
|
(base:Base,mixin:Mixin,key:string,...fields:Field[]):ComposedClass<Base,Mixin,typeof key,Field>{
|
|
248
289
|
const compObj = base as any;
|
|
@@ -277,7 +318,7 @@ export function composeClassPart
|
|
|
277
318
|
}
|
|
278
319
|
|
|
279
320
|
/**根据 MIXIN_FIELDS 自动混入 */
|
|
280
|
-
|
|
321
|
+
static composeMixinable
|
|
281
322
|
<Base extends object, Mixins extends Mixinable<any>[]>
|
|
282
323
|
(base:Base,...mixins:Mixins):
|
|
283
324
|
ComposedMixinable<Base,Mixins>{
|
|
@@ -292,7 +333,7 @@ export function composeMixinable
|
|
|
292
333
|
else
|
|
293
334
|
fieldsSet.add(fixField);
|
|
294
335
|
}
|
|
295
|
-
out = composeClassPart(base,mixin,mixin.MIXIN_KEY,...mixin.MIXIN_FIELDS);
|
|
336
|
+
out = UtilFunc.composeClassPart(base,mixin,mixin.MIXIN_KEY,...mixin.MIXIN_FIELDS);
|
|
296
337
|
}
|
|
297
338
|
return out as any;
|
|
298
339
|
}
|
|
@@ -304,7 +345,7 @@ export function composeMixinable
|
|
|
304
345
|
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
305
346
|
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
306
347
|
*/
|
|
307
|
-
|
|
348
|
+
static mapEntries<T extends Object>
|
|
308
349
|
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
309
350
|
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
310
351
|
result[key as keyof T] = mapper(key as keyof T, value);
|
|
@@ -312,4 +353,15 @@ export function mapEntries<T extends Object>
|
|
|
312
353
|
}, {} as T);
|
|
313
354
|
}
|
|
314
355
|
|
|
356
|
+
/**将JToken转换为字符串
|
|
357
|
+
* @param token - 待转换的Token
|
|
358
|
+
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
359
|
+
* @returns 转换完成的字符串
|
|
360
|
+
*/
|
|
361
|
+
static stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\t"){
|
|
362
|
+
if(space==null)
|
|
363
|
+
space=undefined;
|
|
364
|
+
return JSON.stringify(token,null,space);
|
|
365
|
+
}
|
|
366
|
+
|
|
315
367
|
}
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Completed, Failed, Terminated } from "./UtilSymbol";
|
|
1
2
|
|
|
2
3
|
|
|
3
4
|
/**可以序列化为JSON文件的对象 */
|
|
@@ -16,16 +17,9 @@ export interface IJData{
|
|
|
16
17
|
*/
|
|
17
18
|
toJSON():JToken;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* @returns 转换完成的字符串
|
|
23
|
-
*/
|
|
24
|
-
export function stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\t"){
|
|
25
|
-
if(space==null)
|
|
26
|
-
space=undefined;
|
|
27
|
-
return JSON.stringify(token,null,space);
|
|
28
|
-
}
|
|
20
|
+
|
|
21
|
+
/**任意可作为键值的类型 */
|
|
22
|
+
export type Keyable = string | number | symbol;
|
|
29
23
|
|
|
30
24
|
/**转为可写的 */
|
|
31
25
|
export type Writeable<T> = {
|
|
@@ -73,18 +67,17 @@ export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string
|
|
|
73
67
|
|
|
74
68
|
|
|
75
69
|
/**请求完成状态 成功/失败/终止
|
|
76
|
-
*
|
|
70
|
+
* 成功 将直接返回 结果
|
|
71
|
+
* 终止 将直接返回 null
|
|
77
72
|
* 失败 将重试
|
|
78
73
|
*/
|
|
79
|
-
export type PromiseStat =
|
|
74
|
+
export type PromiseStat = Completed|Failed|Terminated;
|
|
80
75
|
/**promise验证函数 */
|
|
81
76
|
export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
|
|
82
|
-
/**发起promise的函数 */
|
|
83
|
-
export type PromiseProcFn<T> = ()=>Promise<T>;
|
|
84
77
|
|
|
85
78
|
/**类型中任意函数的字符串名称 */
|
|
86
79
|
export type FuncPropNames<T> = {
|
|
87
|
-
[K in keyof T]: T[K] extends (...args:
|
|
80
|
+
[K in keyof T]: T[K] extends (...args: unknown[]) => unknown ? K : never;
|
|
88
81
|
}[keyof T];
|
|
89
82
|
|
|
90
83
|
/**部分组合的类
|
|
@@ -92,7 +85,7 @@ export type FuncPropNames<T> = {
|
|
|
92
85
|
* @template Mixin - 待混入的类
|
|
93
86
|
* @template PropKeys - 需要混入的成员key
|
|
94
87
|
*/
|
|
95
|
-
export type ComposedClass<Base
|
|
88
|
+
export type ComposedClass<Base, Mixin, Key extends string, PropKeys extends keyof Mixin> =
|
|
96
89
|
Base & Pick<Mixin, PropKeys> & {[P in Key]:Mixin};
|
|
97
90
|
|
|
98
91
|
/**可自动混入的类型 */
|
|
@@ -108,9 +101,56 @@ export type Mixinable<Mixin> = {
|
|
|
108
101
|
};
|
|
109
102
|
|
|
110
103
|
/**自动组合可混入的类 */
|
|
111
|
-
export type ComposedMixinable<B
|
|
104
|
+
export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
112
105
|
Ms extends [infer M, ...infer Rest]
|
|
113
106
|
? M extends Mixinable<M>
|
|
114
107
|
? ComposedMixinable<ComposedClass<B,M,M['MIXIN_KEY'],M['MIXIN_FIELDS'][number]>,Rest>
|
|
115
108
|
: "一个混入类没有实现 Mixinable<self>" & Error
|
|
116
109
|
: B
|
|
110
|
+
|
|
111
|
+
/** extends封装
|
|
112
|
+
* @template B - 基础类型
|
|
113
|
+
* @template T - 判断的目标类型
|
|
114
|
+
* @template Y - 如果为真的返回值
|
|
115
|
+
* @template N - 如果为假的返回值
|
|
116
|
+
*/
|
|
117
|
+
export type ExtendThen<B,T,Y,N = never> = B extends T ? Y : N;
|
|
118
|
+
/** 一个联合类型 B 中如果包含 T
|
|
119
|
+
* @template B - 基础类型
|
|
120
|
+
* @template T - 判断的目标类型
|
|
121
|
+
* @template Y - 如果为真的返回值
|
|
122
|
+
* @template N - 如果为假的返回值
|
|
123
|
+
*/
|
|
124
|
+
export type UnionInclude<B,T,Y,N = never> =
|
|
125
|
+
B extends Exclude<B,T>
|
|
126
|
+
? Y
|
|
127
|
+
: N
|
|
128
|
+
/**排除可选字段 */
|
|
129
|
+
export type RequiredOnly<T> = {
|
|
130
|
+
[K in keyof T as
|
|
131
|
+
UnionInclude<T[K],undefined,never,K>
|
|
132
|
+
]: T[K]
|
|
133
|
+
};
|
|
134
|
+
/**添加前缀 */
|
|
135
|
+
export type WithPrefix<T,P extends string> = {
|
|
136
|
+
[K in (keyof T) as
|
|
137
|
+
K extends string
|
|
138
|
+
? `${P}_${K}`
|
|
139
|
+
: K
|
|
140
|
+
]: T[K]
|
|
141
|
+
};
|
|
142
|
+
/**返回结果
|
|
143
|
+
* @template K - 类型键值
|
|
144
|
+
* @template V - 值
|
|
145
|
+
*/
|
|
146
|
+
export type Outcome<K extends Keyable,V> = {
|
|
147
|
+
/**状态类型 */
|
|
148
|
+
status:K;
|
|
149
|
+
/**值 */
|
|
150
|
+
result:V;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**从联合 Outcome 中 根据 id 提取对应 value 的 type */
|
|
154
|
+
export type ExtractOutcome<T,K extends Keyable> =
|
|
155
|
+
T extends Outcome<K,unknown> ? T : never;
|
|
156
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**完成 */
|
|
2
|
+
export const Completed = Symbol("Completed");
|
|
3
|
+
export type Completed = typeof Completed;
|
|
4
|
+
/**失败 */
|
|
5
|
+
export const Failed = Symbol("Failed");
|
|
6
|
+
export type Failed = typeof Failed;
|
|
7
|
+
/**终止 */
|
|
8
|
+
export const Terminated = Symbol("Terminated");
|
|
9
|
+
export type Terminated = typeof Terminated;
|
|
10
|
+
/**不存在 */
|
|
11
|
+
export const None = Symbol("None");
|
|
12
|
+
export type None = typeof None;
|
|
13
|
+
/**超时 */
|
|
14
|
+
export const Timeout = Symbol("Timeout");
|
|
15
|
+
export type Timeout = typeof Timeout;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './UtilFunctions';
|
|
2
2
|
export * from './UtilInterfaces';
|
|
3
|
+
export * from './UtilSymbol';
|
|
3
4
|
export * from './UtilClass';
|
|
4
5
|
export * from './UtilCom';
|
|
5
6
|
export * from './UtilCodecs';
|
|
@@ -7,4 +8,5 @@ export * from './UtilFfmpegTools';
|
|
|
7
8
|
export * from './UtilDecorators';
|
|
8
9
|
export * from './UtilFileTools';
|
|
9
10
|
export * from './UtilLogger';
|
|
10
|
-
export * from './UtilFP';
|
|
11
|
+
export * from './UtilFP';
|
|
12
|
+
export * from './QuickFunction';
|
package/src/test/composeTest.ts
CHANGED
|
@@ -104,4 +104,31 @@ let jot = {
|
|
|
104
104
|
UtilFunc.initObject(jot,{
|
|
105
105
|
c:()=>console.log("缺少c"+insd.getNum())
|
|
106
106
|
})
|
|
107
|
-
jot//?
|
|
107
|
+
jot//?
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
type IfUndefined<T, Y, N> = T extends undefined ? Y : N;
|
|
111
|
+
|
|
112
|
+
type RequiredOnly<T> = {
|
|
113
|
+
[K in (keyof T) as
|
|
114
|
+
T[K] extends Exclude<T[K],undefined>
|
|
115
|
+
? K
|
|
116
|
+
: never
|
|
117
|
+
]: T[K]
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
type WithPrefix<T,P extends string> = {
|
|
122
|
+
[K in (keyof T) as
|
|
123
|
+
K extends string
|
|
124
|
+
? `${P}_${K}`
|
|
125
|
+
: K
|
|
126
|
+
]: T[K]
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type a= {
|
|
130
|
+
abc:123
|
|
131
|
+
def?:1
|
|
132
|
+
}
|
|
133
|
+
type d = RequiredOnly<a>;
|
|
134
|
+
type b = WithPrefix<a,"prefix">;
|