Skip to content

Commit 1993586

Browse files
committed
feat(core/utils): add catchError and secureCall utility functions with tests #136
1 parent 7015c8c commit 1993586

File tree

2 files changed

+211
-3
lines changed

2 files changed

+211
-3
lines changed

packages/core/__tests__/unit/utils/basic.test.ts

+165-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { expect, test } from "vitest";
2-
3-
import { callUntilEnd } from "@/main";
1+
import { callUntilEnd, catchError, secureCall } from "@/main";
2+
import { expect, test, vi } from "vitest";
43

54
test("Call until end", async () => {
65
const startT = Date.now();
@@ -31,3 +30,166 @@ test("Call promise until end", async () => {
3130
expect(Date.now() - startT).toBeGreaterThanOrEqual(250);
3231
expect(i).toBe(5);
3332
});
33+
34+
test("catchError with sync function", async () => {
35+
let error: any;
36+
37+
catchError(
38+
() => 0,
39+
() => {
40+
error = true;
41+
}
42+
);
43+
expect(error).toBeUndefined();
44+
45+
catchError(
46+
() => {
47+
throw new Error("Test Error");
48+
},
49+
() => {
50+
error = true;
51+
}
52+
);
53+
expect(error).toBe(true);
54+
55+
expect(
56+
catchError(
57+
() => {
58+
throw new Error("Test Error");
59+
},
60+
() => 0
61+
)
62+
).toBeInstanceOf(Error);
63+
64+
expect(
65+
await catchError(
66+
() => {
67+
throw new Error("Test Error");
68+
},
69+
() => 0
70+
)
71+
).toBeInstanceOf(Error);
72+
73+
expect(catchError(() => 1)).toBe(1);
74+
75+
expect(await catchError(() => 1)).toBe(1);
76+
77+
const consoleErrorSpy = vi
78+
.spyOn(console, "error")
79+
.mockImplementation(() => {});
80+
const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
81+
catchError(() => {
82+
throw new Error("Test Error");
83+
});
84+
expect(consoleErrorSpy).toHaveBeenCalledWith(new Error("Test Error"));
85+
expect(consoleWarnSpy).toHaveBeenCalledWith(
86+
"[Fastjs warn] fastjs/utils/catchError: An error occurred while executing the function\n" +
87+
" > Error: Test Error"
88+
);
89+
consoleErrorSpy.mockRestore();
90+
consoleWarnSpy.mockRestore();
91+
});
92+
93+
test("catchError with async function", async () => {
94+
let error: any;
95+
96+
await catchError(
97+
async () => 1,
98+
() => {
99+
error = true;
100+
}
101+
);
102+
expect(error).toBeUndefined();
103+
104+
await catchError(
105+
async () => {
106+
throw new Error("Test Error");
107+
},
108+
() => {
109+
error = true;
110+
}
111+
);
112+
expect(error).toBe(true);
113+
114+
const err = catchError(
115+
async () => {
116+
throw new Error("Test Error");
117+
},
118+
() => 0
119+
);
120+
expect(err).toBeInstanceOf(Promise);
121+
122+
const res = await catchError(async () => {
123+
return new Promise((resolve) => {
124+
setTimeout(() => resolve(1), 200);
125+
});
126+
});
127+
expect(res).toBe(1);
128+
129+
const consoleErrorSpy = vi
130+
.spyOn(console, "error")
131+
.mockImplementation(() => {});
132+
const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
133+
await catchError(async () => {
134+
throw new Error("Test Error");
135+
});
136+
expect(consoleErrorSpy).toHaveBeenCalledWith(new Error("Test Error"));
137+
expect(consoleWarnSpy).toHaveBeenCalledWith(
138+
"[Fastjs warn] fastjs/utils/catchError: An error occurred while executing the function\n" +
139+
" > Error: Test Error"
140+
);
141+
consoleErrorSpy.mockRestore();
142+
consoleWarnSpy.mockRestore();
143+
});
144+
145+
test("secureCall with sync function", async () => {
146+
const error = new Error("Test Error");
147+
148+
expect(
149+
secureCall(() => {
150+
throw error;
151+
})
152+
).toStrictEqual([undefined, error]);
153+
154+
expect(
155+
secureCall(() => {
156+
return 1;
157+
})
158+
).toStrictEqual([1, null]);
159+
160+
expect(
161+
await secureCall(() => {
162+
throw error;
163+
})
164+
).toStrictEqual([undefined, error]);
165+
166+
expect(
167+
await secureCall(() => {
168+
return 1;
169+
})
170+
).toStrictEqual([1, null]);
171+
});
172+
173+
test("secureCall with async function", async () => {
174+
const error = new Error("Test Error");
175+
176+
expect(
177+
await secureCall(async () => {
178+
throw error;
179+
})
180+
).toStrictEqual([undefined, error]);
181+
182+
expect(
183+
await secureCall(async () => {
184+
return 1;
185+
})
186+
).toStrictEqual([1, null]);
187+
188+
expect(
189+
await secureCall(async () => {
190+
return new Promise((resolve) => {
191+
setTimeout(() => resolve(1), 200);
192+
});
193+
})
194+
).toStrictEqual([1, null]);
195+
});

packages/core/src/utils/basic.ts

+46
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,49 @@ export async function callUntilEnd(
4040
}
4141
});
4242
}
43+
44+
export function catchError(
45+
func: () => Promise<any> | any,
46+
onError?: (error: Error) => void
47+
): Promise<any> | any {
48+
const err = (error: Error) => {
49+
if (__DEV__) {
50+
_dev.warn(
51+
"fastjs/utils/catchError",
52+
"An error occurred while executing the function",
53+
[error.toString()]
54+
);
55+
}
56+
if (onError) onError(error);
57+
else console.error(error);
58+
return error;
59+
};
60+
61+
try {
62+
const res = func();
63+
if (res instanceof Promise) {
64+
return res.then((res) => res).catch(err);
65+
}
66+
return res;
67+
} catch (error: any) {
68+
return err(error);
69+
}
70+
}
71+
72+
export function secureCall(
73+
func: () => Promise<any> | any
74+
): [any, Error | null] | Promise<[any, Error | null]> {
75+
try {
76+
const res = func();
77+
if (res instanceof Promise) {
78+
return new Promise((resolve, reject) => {
79+
res
80+
.then((res) => resolve([res, null]))
81+
.catch((error) => resolve([undefined, error]));
82+
});
83+
}
84+
return [res, null];
85+
} catch (error: any) {
86+
return [undefined, error];
87+
}
88+
}

0 commit comments

Comments
 (0)