Files
rustfs-console/composables/useAsyncOperation.ts
T
overtrue 0598f8065f refactor: 修复 API 客户端 composables 滥用和硬编码路径问题
- 修复 lib/api-client.ts 中在类方法中直接调用 composables 的问题
- 添加 ApiErrorHandler 错误处理器,通过依赖注入方式处理 401 错误
- 创建路由工具函数 utils/routes.ts,统一管理路由路径
- 修复 composables/useAuth.ts 中的硬编码路径,使用工具函数
- 修复 components/copy-input.vue 的生命周期问题,在 onMounted 中创建 ClipboardJS 实例
- 修复 plugins/03.s3.ts 中的错误处理,使用 navigateTo 替代直接操作 window.location
- 修复 pages/config.vue 中的硬编码路径
- 添加 composables/useFormValidation.ts、useAsyncOperation.ts、useErrorHandler.ts 工具函数(供后续使用)
- 添加 types/api.ts 类型定义
2025-10-31 22:50:59 +08:00

137 lines
2.9 KiB
TypeScript

/**
* 统一的异步操作管理 Composable
* 提供加载状态、错误处理和重试机制
*/
import { ref, readonly, type Ref } from 'vue';
import { useErrorHandler } from './useErrorHandler';
export interface AsyncOperationOptions {
/**
* 是否自动处理错误
* @default true
*/
autoHandleError?: boolean;
/**
* 默认错误消息
*/
defaultErrorMessage?: string;
/**
* 重试次数
* @default 0
*/
retries?: number;
/**
* 重试延迟(毫秒)
* @default 1000
*/
retryDelay?: number;
}
export interface UseAsyncOperationReturn<T extends (...args: any[]) => Promise<any>> {
/**
* 加载状态(只读)
*/
loading: Readonly<Ref<boolean>>;
/**
* 错误信息(只读)
*/
error: Readonly<Ref<Error | null>>;
/**
* 执行异步操作
*/
execute: (...args: Parameters<T>) => Promise<ReturnType<T> | null>;
/**
* 重置错误状态
*/
resetError: () => void;
}
/**
* 包装异步操作,提供加载状态和错误处理
* @param operation 异步操作函数
* @param options 配置选项
* @returns 包含加载状态和执行函数的对象
*/
export function useAsyncOperation<T extends (...args: any[]) => Promise<any>>(
operation: T,
options: AsyncOperationOptions = {}
): UseAsyncOperationReturn<T> {
const {
autoHandleError = true,
defaultErrorMessage,
retries = 0,
retryDelay = 1000,
} = options;
const loading = ref(false);
const error = ref<Error | null>(null);
const { handleError } = useErrorHandler();
/**
* 执行重试逻辑
*/
const executeWithRetry = async (
...args: Parameters<T>
): Promise<ReturnType<T>> => {
let lastError: Error | null = null;
for (let attempt = 0; attempt <= retries; attempt++) {
try {
return await operation(...args);
} catch (err) {
lastError = err instanceof Error ? err : new Error(String(err));
// 如果不是最后一次尝试,等待后重试
if (attempt < retries) {
await new Promise((resolve) => setTimeout(resolve, retryDelay));
continue;
}
}
}
throw lastError || new Error('Operation failed');
};
/**
* 执行异步操作
*/
const execute = async (
...args: Parameters<T>
): Promise<ReturnType<T> | null> => {
loading.value = true;
error.value = null;
try {
const result = await executeWithRetry(...args);
return result;
} catch (err) {
const errorInstance =
err instanceof Error ? err : new Error(String(err));
error.value = errorInstance;
if (autoHandleError) {
handleError(errorInstance, defaultErrorMessage);
}
return null;
} finally {
loading.value = false;
}
};
/**
* 重置错误状态
*/
const resetError = () => {
error.value = null;
};
return {
loading: readonly(loading),
error: readonly(error),
execute,
resetError,
};
}