You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
35 lines
1.1 KiB
35 lines
1.1 KiB
import { useCallback, useState } from "react";
|
|
import { Message } from "@arco-design/web-react";
|
|
import i18n from "@/i18n";
|
|
|
|
/**
|
|
* 安全执行异步操作:自动 try-catch、loading、错误提示
|
|
* @param asyncFn 异步函数
|
|
* @returns [执行函数, loading]
|
|
*/
|
|
export function useSafeAsync<T extends unknown[], R>(
|
|
asyncFn: (...args: T) => Promise<R>,
|
|
options?: { successMsg?: string; errMsg?: string }
|
|
) {
|
|
const [loading, setLoading] = useState(false);
|
|
const run = useCallback(
|
|
async (...args: T): Promise<R | undefined> => {
|
|
setLoading(true);
|
|
try {
|
|
const result = await asyncFn(...args);
|
|
if (options?.successMsg) {
|
|
Message.success(options.successMsg);
|
|
}
|
|
return result;
|
|
} catch (e) {
|
|
const msg = options?.errMsg ?? (e instanceof Error ? e.message : i18n.t("common.operate_failed"));
|
|
Message.error(msg);
|
|
return undefined;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
},
|
|
[asyncFn, options?.successMsg, options?.errMsg]
|
|
);
|
|
return [run, loading] as const;
|
|
}
|
|
|