@taicode/common-base 1.5.1 → 1.6.1
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/output/catch/catch.d.ts +39 -3
- package/output/catch/catch.d.ts.map +1 -1
- package/output/catch/catch.js +28 -10
- package/output/catch/catch.test.js +34 -354
- package/package.json +1 -1
package/output/catch/catch.d.ts
CHANGED
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
type CatchType<F extends () => unknown> = F extends () => PromiseLike<infer R> ? R : F extends () => infer R ? R : never;
|
|
2
|
+
/**
|
|
3
|
+
* 成功结果类型
|
|
4
|
+
* 只包含 value 字段,error 字段为 undefined
|
|
5
|
+
*/
|
|
6
|
+
export interface CatchSuccess<T> {
|
|
7
|
+
value: T;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 失败结果类型
|
|
11
|
+
* error 字段类型永远为 unknown(或用户自定义),这样最安全,防止误用。
|
|
12
|
+
* 推荐在 error 分支内用 instanceof/typeof 等类型守卫自行收窄类型。
|
|
13
|
+
*/
|
|
14
|
+
export interface CatchFailure<E> {
|
|
15
|
+
error: E;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 捕获结果联合类型,使用判别联合类型以支持类型守卫
|
|
19
|
+
*
|
|
20
|
+
* 设计说明:
|
|
21
|
+
* - 通过 isError 方法进行类型守卫,推荐始终用 result.isError() 判断是否为错误分支。
|
|
22
|
+
* - isError 方法为 function 写法(而非箭头函数),以支持类型谓词,且 this 不会被转移。
|
|
23
|
+
* - 不建议直接用 error !== undefined 判断错误分支,该方式依赖 error 的值,推荐统一用 isError()。
|
|
24
|
+
*/
|
|
25
|
+
export type CatchResult<T, E = unknown> = (CatchSuccess<T> | CatchFailure<E>) & {
|
|
26
|
+
/**
|
|
27
|
+
* 类型守卫方法,判断当前对象是否为 CatchFailure。
|
|
28
|
+
* function 写法,返回类型谓词,保证类型收窄。
|
|
29
|
+
* 推荐用法:if (result.isError()) { ... }
|
|
30
|
+
*/
|
|
31
|
+
isError: (this: unknown) => this is CatchFailure<E>;
|
|
32
|
+
};
|
|
2
33
|
/**
|
|
3
34
|
* 通用错误捕获函数,支持 PromiseLike 和函数执行
|
|
4
|
-
*
|
|
35
|
+
* 返回 { value, error } 的对象格式,便于类型判断
|
|
36
|
+
*
|
|
37
|
+
* 设计说明:
|
|
38
|
+
* - 支持同步/异步/thenable 场景
|
|
39
|
+
* - 推荐通过 isError() 进行类型守卫
|
|
40
|
+
* - error 字段类型为 unknown,需用户自行收窄
|
|
5
41
|
*/
|
|
6
|
-
export declare function catchIt<T>(input: PromiseLike<T>): Promise<
|
|
7
|
-
export declare function catchIt<F extends () => unknown>(input: F): Promise<
|
|
42
|
+
export declare function catchIt<T, E = unknown>(input: PromiseLike<T>): Promise<CatchResult<T, E>>;
|
|
43
|
+
export declare function catchIt<F extends () => unknown, E = unknown>(input: F): Promise<CatchResult<CatchType<F>, E>>;
|
|
8
44
|
export {};
|
|
9
45
|
//# sourceMappingURL=catch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catch.d.ts","sourceRoot":"","sources":["../../source/catch/catch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"catch.d.ts","sourceRoot":"","sources":["../../source/catch/catch.ts"],"names":[],"mappings":"AAMA,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,OAAO,IAAI,CAAC,SAAS,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAExH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAA;CACT;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAA;CACT;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAC9E;;;;OAIG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAAA;CACpD,CAAA;AA0BD;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAChG,wBAAsB,OAAO,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA"}
|
package/output/catch/catch.js
CHANGED
|
@@ -2,29 +2,47 @@
|
|
|
2
2
|
function isPromiseLike(value) {
|
|
3
3
|
return value != null && typeof value === 'object' && 'then' in value && typeof value.then === 'function';
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* 构造成功结果对象
|
|
7
|
+
* isError 始终返回 false
|
|
8
|
+
*/
|
|
9
|
+
function createSuccess(value) {
|
|
10
|
+
return {
|
|
11
|
+
value,
|
|
12
|
+
error: undefined,
|
|
13
|
+
isError() { return false; }
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 构造失败结果对象
|
|
18
|
+
* isError 始终返回 true
|
|
19
|
+
*/
|
|
20
|
+
function createFailure(error) {
|
|
21
|
+
return {
|
|
22
|
+
error,
|
|
23
|
+
value: undefined,
|
|
24
|
+
isError() { return true; }
|
|
25
|
+
};
|
|
26
|
+
}
|
|
5
27
|
export async function catchIt(input) {
|
|
6
|
-
const returned = [undefined, undefined];
|
|
7
28
|
try {
|
|
8
29
|
if (isPromiseLike(input)) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.then((result) => (returned[0] = result))
|
|
12
|
-
.catch((error) => (returned[1] = error));
|
|
30
|
+
const result = await Promise.resolve(input);
|
|
31
|
+
return createSuccess(result);
|
|
13
32
|
}
|
|
14
33
|
else if (typeof input === 'function') {
|
|
15
|
-
// 处理函数
|
|
16
34
|
const result = input();
|
|
17
35
|
if (isPromiseLike(result)) {
|
|
18
|
-
// 如果函数返回 PromiseLike,递归调用
|
|
19
36
|
return catchIt(result);
|
|
20
37
|
}
|
|
21
38
|
else {
|
|
22
|
-
|
|
39
|
+
return createSuccess(result);
|
|
23
40
|
}
|
|
24
41
|
}
|
|
25
42
|
}
|
|
26
43
|
catch (error) {
|
|
27
|
-
|
|
44
|
+
return createFailure(error);
|
|
28
45
|
}
|
|
29
|
-
|
|
46
|
+
// 理论上不会到达这里,兜底类型安全
|
|
47
|
+
return createFailure(new Error('Unexpected input type'));
|
|
30
48
|
}
|
|
@@ -1,363 +1,43 @@
|
|
|
1
|
-
import { describe, it, expect
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { catchIt } from './catch';
|
|
3
3
|
describe('catchIt', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
expect(result).toBe(successValue);
|
|
10
|
-
expect(error).toBeUndefined();
|
|
11
|
-
});
|
|
12
|
-
it('应该正确处理失败的 Promise', async () => {
|
|
13
|
-
const errorValue = new Error('test error');
|
|
14
|
-
const promise = Promise.reject(errorValue);
|
|
15
|
-
const [result, error] = await catchIt(promise);
|
|
16
|
-
expect(result).toBeUndefined();
|
|
17
|
-
expect(error).toBe(errorValue);
|
|
18
|
-
});
|
|
19
|
-
it('应该正确处理返回不同数据类型的 Promise', async () => {
|
|
20
|
-
// 数字类型
|
|
21
|
-
const [numberResult, numberError] = await catchIt(Promise.resolve(42));
|
|
22
|
-
expect(numberResult).toBe(42);
|
|
23
|
-
expect(numberError).toBeUndefined();
|
|
24
|
-
// 对象类型
|
|
25
|
-
const obj = { key: 'value' };
|
|
26
|
-
const [objectResult, objectError] = await catchIt(Promise.resolve(obj));
|
|
27
|
-
expect(objectResult).toBe(obj);
|
|
28
|
-
expect(objectError).toBeUndefined();
|
|
29
|
-
// 数组类型
|
|
30
|
-
const arr = [1, 2, 3];
|
|
31
|
-
const [arrayResult, arrayError] = await catchIt(Promise.resolve(arr));
|
|
32
|
-
expect(arrayResult).toBe(arr);
|
|
33
|
-
expect(arrayError).toBeUndefined();
|
|
34
|
-
// null 和 undefined
|
|
35
|
-
const [nullResult, nullError] = await catchIt(Promise.resolve(null));
|
|
36
|
-
expect(nullResult).toBeNull();
|
|
37
|
-
expect(nullError).toBeUndefined();
|
|
38
|
-
const [undefinedResult, undefinedError] = await catchIt(Promise.resolve(undefined));
|
|
39
|
-
expect(undefinedResult).toBeUndefined();
|
|
40
|
-
expect(undefinedError).toBeUndefined();
|
|
41
|
-
});
|
|
42
|
-
it('应该正确处理不同类型的错误', async () => {
|
|
43
|
-
// Error 对象
|
|
44
|
-
const error = new Error('test error');
|
|
45
|
-
const [, caughtError1] = await catchIt(Promise.reject(error));
|
|
46
|
-
expect(caughtError1).toBe(error);
|
|
47
|
-
// 字符串错误
|
|
48
|
-
const [, caughtError2] = await catchIt(Promise.reject('string error'));
|
|
49
|
-
expect(caughtError2).toBe('string error');
|
|
50
|
-
// 数字错误
|
|
51
|
-
const [, caughtError3] = await catchIt(Promise.reject(404));
|
|
52
|
-
expect(caughtError3).toBe(404);
|
|
53
|
-
// 对象错误
|
|
54
|
-
const objError = { code: 500, message: 'server error' };
|
|
55
|
-
const [, caughtError4] = await catchIt(Promise.reject(objError));
|
|
56
|
-
expect(caughtError4).toBe(objError);
|
|
57
|
-
});
|
|
4
|
+
it('同步函数返回值应为 value,error 为 undefined,isError 为 false', async () => {
|
|
5
|
+
const result = await catchIt(() => 123);
|
|
6
|
+
expect(result.value).toBe(123);
|
|
7
|
+
expect(result.error).toBeUndefined();
|
|
8
|
+
expect(result.isError()).toBe(false);
|
|
58
9
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
expect(error).toBeUndefined();
|
|
65
|
-
});
|
|
66
|
-
it('应该正确处理抛出错误的同步函数', async () => {
|
|
67
|
-
const errorValue = new Error('sync error');
|
|
68
|
-
const syncFn = () => {
|
|
69
|
-
throw errorValue;
|
|
70
|
-
};
|
|
71
|
-
const [result, error] = await catchIt(syncFn);
|
|
72
|
-
expect(result).toBeUndefined();
|
|
73
|
-
expect(error).toBe(errorValue);
|
|
74
|
-
});
|
|
75
|
-
it('应该正确处理返回不同数据类型的同步函数', async () => {
|
|
76
|
-
// 数字
|
|
77
|
-
const [numberResult] = await catchIt(() => 42);
|
|
78
|
-
expect(numberResult).toBe(42);
|
|
79
|
-
// 字符串
|
|
80
|
-
const [stringResult] = await catchIt(() => 'hello');
|
|
81
|
-
expect(stringResult).toBe('hello');
|
|
82
|
-
// 对象
|
|
83
|
-
const obj = { test: true };
|
|
84
|
-
const [objectResult] = await catchIt(() => obj);
|
|
85
|
-
expect(objectResult).toBe(obj);
|
|
86
|
-
// 数组
|
|
87
|
-
const arr = [1, 2, 3];
|
|
88
|
-
const [arrayResult] = await catchIt(() => arr);
|
|
89
|
-
expect(arrayResult).toBe(arr);
|
|
90
|
-
// boolean
|
|
91
|
-
const [boolResult] = await catchIt(() => true);
|
|
92
|
-
expect(boolResult).toBe(true);
|
|
93
|
-
// null
|
|
94
|
-
const [nullResult] = await catchIt(() => null);
|
|
95
|
-
expect(nullResult).toBeNull();
|
|
96
|
-
// undefined
|
|
97
|
-
const [undefinedResult] = await catchIt(() => undefined);
|
|
98
|
-
expect(undefinedResult).toBeUndefined();
|
|
99
|
-
});
|
|
100
|
-
it('应该确保同步函数被调用', async () => {
|
|
101
|
-
const mockFn = vi.fn(() => 'test');
|
|
102
|
-
await catchIt(mockFn);
|
|
103
|
-
expect(mockFn).toHaveBeenCalledOnce();
|
|
104
|
-
});
|
|
10
|
+
it('异步函数返回值应为 value,error 为 undefined,isError 为 false', async () => {
|
|
11
|
+
const result = await catchIt(async () => 456);
|
|
12
|
+
expect(result.value).toBe(456);
|
|
13
|
+
expect(result.error).toBeUndefined();
|
|
14
|
+
expect(result.isError()).toBe(false);
|
|
105
15
|
});
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
it('应该正确处理返回失败 Promise 的函数', async () => {
|
|
114
|
-
const errorValue = new Error('async error');
|
|
115
|
-
const asyncFn = () => Promise.reject(errorValue);
|
|
116
|
-
const [result, error] = await catchIt(asyncFn);
|
|
117
|
-
expect(result).toBeUndefined();
|
|
118
|
-
expect(error).toBe(errorValue);
|
|
119
|
-
});
|
|
120
|
-
it('应该正确处理返回不同数据类型 Promise 的函数', async () => {
|
|
121
|
-
// 数字
|
|
122
|
-
const [numberResult] = await catchIt(() => Promise.resolve(123));
|
|
123
|
-
expect(numberResult).toBe(123);
|
|
124
|
-
// 对象
|
|
125
|
-
const obj = { async: true };
|
|
126
|
-
const [objectResult] = await catchIt(() => Promise.resolve(obj));
|
|
127
|
-
expect(objectResult).toBe(obj);
|
|
128
|
-
});
|
|
129
|
-
it('应该确保返回 Promise 的函数被调用', async () => {
|
|
130
|
-
const mockAsyncFn = vi.fn(() => Promise.resolve('test'));
|
|
131
|
-
await catchIt(mockAsyncFn);
|
|
132
|
-
expect(mockAsyncFn).toHaveBeenCalledOnce();
|
|
133
|
-
});
|
|
16
|
+
it('同步抛出异常时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
17
|
+
const error = new Error('fail');
|
|
18
|
+
const result = await catchIt(() => { throw error; });
|
|
19
|
+
expect(result.value).toBeUndefined();
|
|
20
|
+
expect(result.error).toBe(error);
|
|
21
|
+
expect(result.isError()).toBe(true);
|
|
134
22
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const [result, error] = await catchIt(errorFn);
|
|
142
|
-
expect(result).toBeUndefined();
|
|
143
|
-
expect(error).toBe(syncError);
|
|
144
|
-
});
|
|
145
|
-
it('应该正确处理 Promise 链中的错误', async () => {
|
|
146
|
-
const chainError = new Error('chain error');
|
|
147
|
-
const promise = Promise.resolve()
|
|
148
|
-
.then(() => {
|
|
149
|
-
throw chainError;
|
|
150
|
-
});
|
|
151
|
-
const [result, error] = await catchIt(promise);
|
|
152
|
-
expect(result).toBeUndefined();
|
|
153
|
-
expect(error).toBe(chainError);
|
|
154
|
-
});
|
|
155
|
-
it('应该正确处理延迟的 Promise', async () => {
|
|
156
|
-
const delayedPromise = new Promise((resolve) => {
|
|
157
|
-
setTimeout(() => resolve('delayed result'), 10);
|
|
158
|
-
});
|
|
159
|
-
const [result, error] = await catchIt(delayedPromise);
|
|
160
|
-
expect(result).toBe('delayed result');
|
|
161
|
-
expect(error).toBeUndefined();
|
|
162
|
-
});
|
|
163
|
-
it('应该正确处理返回 falsy 值的函数', async () => {
|
|
164
|
-
// 返回 0
|
|
165
|
-
const [zeroResult] = await catchIt(() => 0);
|
|
166
|
-
expect(zeroResult).toBe(0);
|
|
167
|
-
// 返回空字符串
|
|
168
|
-
const [emptyStringResult] = await catchIt(() => '');
|
|
169
|
-
expect(emptyStringResult).toBe('');
|
|
170
|
-
// 返回 false
|
|
171
|
-
const [falseResult] = await catchIt(() => false);
|
|
172
|
-
expect(falseResult).toBe(false);
|
|
173
|
-
// 返回 null
|
|
174
|
-
const [nullResult] = await catchIt(() => null);
|
|
175
|
-
expect(nullResult).toBeNull();
|
|
176
|
-
// 返回 undefined
|
|
177
|
-
const [undefinedResult] = await catchIt(() => undefined);
|
|
178
|
-
expect(undefinedResult).toBeUndefined();
|
|
179
|
-
});
|
|
23
|
+
it('异步抛出异常时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
24
|
+
const error = new Error('fail-async');
|
|
25
|
+
const result = await catchIt(() => Promise.reject(error));
|
|
26
|
+
expect(result.value).toBeUndefined();
|
|
27
|
+
expect(result.error).toBe(error);
|
|
28
|
+
expect(result.isError()).toBe(true);
|
|
180
29
|
});
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// stringResult 应该被推导为 string | undefined
|
|
187
|
-
const numberPromise = Promise.resolve(42);
|
|
188
|
-
const [numberResult] = await catchIt(numberPromise);
|
|
189
|
-
// numberResult 应该被推导为 number | undefined
|
|
190
|
-
// 运行时验证
|
|
191
|
-
expect(typeof stringResult).toBe('string');
|
|
192
|
-
expect(typeof numberResult).toBe('number');
|
|
193
|
-
});
|
|
194
|
-
it('应该保持正确的类型推导 - 同步函数', async () => {
|
|
195
|
-
const stringFn = () => 'hello';
|
|
196
|
-
const [stringResult] = await catchIt(stringFn);
|
|
197
|
-
const numberFn = () => 42;
|
|
198
|
-
const [numberResult] = await catchIt(numberFn);
|
|
199
|
-
// 运行时验证
|
|
200
|
-
expect(typeof stringResult).toBe('string');
|
|
201
|
-
expect(typeof numberResult).toBe('number');
|
|
202
|
-
});
|
|
203
|
-
it('应该保持正确的类型推导 - 异步函数', async () => {
|
|
204
|
-
const asyncStringFn = () => Promise.resolve('async hello');
|
|
205
|
-
const [asyncStringResult] = await catchIt(asyncStringFn);
|
|
206
|
-
const asyncNumberFn = () => Promise.resolve(100);
|
|
207
|
-
const [asyncNumberResult] = await catchIt(asyncNumberFn);
|
|
208
|
-
// 运行时验证
|
|
209
|
-
expect(typeof asyncStringResult).toBe('string');
|
|
210
|
-
expect(typeof asyncNumberResult).toBe('number');
|
|
211
|
-
});
|
|
30
|
+
it('PromiseLike resolve 时应返回 value,error 为 undefined,isError 为 false', async () => {
|
|
31
|
+
const result = await catchIt(Promise.resolve('ok'));
|
|
32
|
+
expect(result.value).toBe('ok');
|
|
33
|
+
expect(result.error).toBeUndefined();
|
|
34
|
+
expect(result.isError()).toBe(false);
|
|
212
35
|
});
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
});
|
|
220
|
-
const [result, error] = await catchIt(mockApiCall);
|
|
221
|
-
expect(result).toEqual({ data: { id: 1, name: 'test' }, status: 200 });
|
|
222
|
-
expect(error).toBeUndefined();
|
|
223
|
-
// 模拟失败的 API 调用
|
|
224
|
-
const failedApiCall = () => Promise.reject({
|
|
225
|
-
status: 404,
|
|
226
|
-
message: 'Not Found'
|
|
227
|
-
});
|
|
228
|
-
const [failedResult, apiError] = await catchIt(failedApiCall);
|
|
229
|
-
expect(failedResult).toBeUndefined();
|
|
230
|
-
expect(apiError).toEqual({ status: 404, message: 'Not Found' });
|
|
231
|
-
});
|
|
232
|
-
it('应该适用于文件操作场景', async () => {
|
|
233
|
-
// 模拟成功的文件读取
|
|
234
|
-
const mockFileRead = () => Promise.resolve('file content');
|
|
235
|
-
const [content, error] = await catchIt(mockFileRead);
|
|
236
|
-
expect(content).toBe('file content');
|
|
237
|
-
expect(error).toBeUndefined();
|
|
238
|
-
// 模拟失败的文件读取
|
|
239
|
-
const failedFileRead = () => Promise.reject(new Error('File not found'));
|
|
240
|
-
const [failedContent, fileError] = await catchIt(failedFileRead);
|
|
241
|
-
expect(failedContent).toBeUndefined();
|
|
242
|
-
expect(fileError).toBeInstanceOf(Error);
|
|
243
|
-
expect(fileError.message).toBe('File not found');
|
|
244
|
-
});
|
|
245
|
-
it('应该适用于数据解析场景', async () => {
|
|
246
|
-
// 模拟成功的 JSON 解析
|
|
247
|
-
const jsonParseSuccess = () => JSON.parse('{"key": "value"}');
|
|
248
|
-
const [parsed, parseError] = await catchIt(jsonParseSuccess);
|
|
249
|
-
expect(parsed).toEqual({ key: 'value' });
|
|
250
|
-
expect(parseError).toBeUndefined();
|
|
251
|
-
// 模拟失败的 JSON 解析
|
|
252
|
-
const jsonParseFailed = () => JSON.parse('invalid json');
|
|
253
|
-
const [failedParsed, jsonError] = await catchIt(jsonParseFailed);
|
|
254
|
-
expect(failedParsed).toBeUndefined();
|
|
255
|
-
expect(jsonError).toBeInstanceOf(SyntaxError);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
describe('处理 PromiseLike 对象', () => {
|
|
259
|
-
it('应该正确处理自定义的 PromiseLike 对象', async () => {
|
|
260
|
-
// 创建自定义的 PromiseLike 对象
|
|
261
|
-
const customPromiseLike = {
|
|
262
|
-
then(onfulfilled, onrejected) {
|
|
263
|
-
try {
|
|
264
|
-
const result = onfulfilled?.('custom promise result');
|
|
265
|
-
return Promise.resolve(result);
|
|
266
|
-
}
|
|
267
|
-
catch (error) {
|
|
268
|
-
return onrejected ? Promise.resolve(onrejected(error)) : Promise.reject(error);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
const [result, error] = await catchIt(customPromiseLike);
|
|
273
|
-
expect(result).toBe('custom promise result');
|
|
274
|
-
expect(error).toBeUndefined();
|
|
275
|
-
});
|
|
276
|
-
it('应该正确处理失败的 PromiseLike 对象', async () => {
|
|
277
|
-
const customError = new Error('custom promise error');
|
|
278
|
-
const failingPromiseLike = {
|
|
279
|
-
then(onfulfilled, onrejected) {
|
|
280
|
-
if (onrejected) {
|
|
281
|
-
return Promise.resolve(onrejected(customError));
|
|
282
|
-
}
|
|
283
|
-
return Promise.reject(customError);
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
const [result, error] = await catchIt(failingPromiseLike);
|
|
287
|
-
expect(result).toBeUndefined();
|
|
288
|
-
expect(error).toBe(customError);
|
|
289
|
-
});
|
|
290
|
-
it('应该正确处理返回 PromiseLike 的函数', async () => {
|
|
291
|
-
const customPromiseLike = {
|
|
292
|
-
then(onfulfilled, onrejected) {
|
|
293
|
-
try {
|
|
294
|
-
const result = onfulfilled?.(42);
|
|
295
|
-
return Promise.resolve(result);
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
return onrejected ? Promise.resolve(onrejected(error)) : Promise.reject(error);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
const fn = () => customPromiseLike;
|
|
303
|
-
const [result, error] = await catchIt(fn);
|
|
304
|
-
expect(result).toBe(42);
|
|
305
|
-
expect(error).toBeUndefined();
|
|
306
|
-
});
|
|
307
|
-
it('应该正确处理第三方库的 PromiseLike 对象', async () => {
|
|
308
|
-
// 模拟第三方库的 PromiseLike 实现 (如 jQuery.Deferred, Bluebird 等)
|
|
309
|
-
class CustomPromise {
|
|
310
|
-
value;
|
|
311
|
-
isResolved = false;
|
|
312
|
-
isRejected = false;
|
|
313
|
-
rejectionReason;
|
|
314
|
-
constructor(executor) {
|
|
315
|
-
const resolve = (value) => {
|
|
316
|
-
this.value = value;
|
|
317
|
-
this.isResolved = true;
|
|
318
|
-
};
|
|
319
|
-
const reject = (reason) => {
|
|
320
|
-
this.rejectionReason = reason;
|
|
321
|
-
this.isRejected = true;
|
|
322
|
-
};
|
|
323
|
-
try {
|
|
324
|
-
executor(resolve, reject);
|
|
325
|
-
}
|
|
326
|
-
catch (error) {
|
|
327
|
-
reject(error);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
then(onfulfilled, onrejected) {
|
|
331
|
-
if (this.isResolved && onfulfilled) {
|
|
332
|
-
try {
|
|
333
|
-
const result = onfulfilled(this.value);
|
|
334
|
-
return Promise.resolve(result);
|
|
335
|
-
}
|
|
336
|
-
catch (error) {
|
|
337
|
-
return Promise.reject(error);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else if (this.isRejected && onrejected) {
|
|
341
|
-
try {
|
|
342
|
-
const result = onrejected(this.rejectionReason);
|
|
343
|
-
return Promise.resolve(result);
|
|
344
|
-
}
|
|
345
|
-
catch (error) {
|
|
346
|
-
return Promise.reject(error);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
else if (this.isRejected) {
|
|
350
|
-
return Promise.reject(this.rejectionReason);
|
|
351
|
-
}
|
|
352
|
-
return Promise.resolve(this.value);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
const customPromise = new CustomPromise((resolve) => {
|
|
356
|
-
resolve('third party promise');
|
|
357
|
-
});
|
|
358
|
-
const [result, error] = await catchIt(customPromise);
|
|
359
|
-
expect(result).toBe('third party promise');
|
|
360
|
-
expect(error).toBeUndefined();
|
|
361
|
-
});
|
|
36
|
+
it('PromiseLike reject 时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
37
|
+
const error = new Error('promise-fail');
|
|
38
|
+
const result = await catchIt(Promise.reject(error));
|
|
39
|
+
expect(result.value).toBeUndefined();
|
|
40
|
+
expect(result.error).toBe(error);
|
|
41
|
+
expect(result.isError()).toBe(true);
|
|
362
42
|
});
|
|
363
43
|
});
|