问题
大量的页面都实现了类似的代码
//提交类
try { const submitResponse = await serviceApply.submit(data); if (submitResponse.status === 'success') {
// 提交如果成功,则将预设存入
if (saveAsPreset.value) {
// 先比对现存预设和本次填报的区别,有区别才添加到预设
const isDuplicate = presets.value.some(preset => JSON.stringify(preset.data) === JSON.stringify(formData));
if (!isDuplicate) {
// 可以选择在这里保存新的预设到服务器,必须符合typePreset.AecvApply类型规范
await servicePreset.create({ id: '', data: formData });
}
}
ElMessage.success('报名成功');
router.push('/apply/progress');
resetForm(true);
dialogVisible.value = false;
} else {
// 遍历 response.errors 数组并显示每个错误消息
if (Array.isArray(submitResponse.errors) && submitResponse.errors.length > 0) {
submitResponse.errors.forEach((error) => {
ElMessage.error(error);
});
} else {
ElMessage.error(submitResponse.message || '未知错误');
}
}
} catch (error) {
ElMessage.error('请求失败,请稍后重试');
}
// 获取类
try {
const response = await serviceApply.historyDetail(record.memberkid);
if (response.status === 'success' && response.data) {
selectedRecord.value = response.data;
} else {
// 遍历 response.errors 数组并显示每个错误消息
if (Array.isArray(response.errors) && response.errors.length > 0) {
response.errors.forEach((error) => { ElMessage.error(error); });
} else {
ElMessage.error(response.message || '无数据');
}
}
} catch (error) {
ElMessage.error('请求失败,请稍后重试');
}
是不是应该有一个函数或工具,能实现这些类似的功能?当然,必须所有参数都可在这个函数工具里设置,也可以就用默认的。
方案
为了减少代码重复,并使逻辑更加清晰和可维护,可以创建一个通用的工具函数来封装这些操作。这种函数不仅可以简化提交和获取数据的流程,还可以提供可配置的默认参数,同时允许在必要时覆盖默认行为。
以下是一个可能的实现思路:
通用工具函数设计
- 封装 HTTP 请求:处理请求、响应、错误、成功和失败的逻辑。
- 提供默认参数:如是否显示消息提示、成功后的回调、失败后的回调等。
- 允许覆盖行为:支持传递额外配置,动态调整行为。
通用函数实现
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
interface RequestOptions<T = any> {
service: (data: T) => Promise<any>; // 服务函数
data?: T; // 请求数据
onSuccess?: (response: any) => void; // 自定义成功回调
onError?: (response: any) => void; // 自定义错误回调
successMessage?: string; // 成功提示消息
errorMessage?: string; // 错误提示消息
redirectTo?: string; // 成功后跳转的路径
handlePreset?: boolean; // 是否处理预设逻辑
presetHandler?: () => Promise<void>; // 处理预设逻辑的函数
}
export async function handleRequest<T = any>({
service,
data,
onSuccess,
onError,
successMessage = '操作成功',
errorMessage = '操作失败,请稍后重试',
redirectTo,
handlePreset = false,
presetHandler,
}: RequestOptions<T>): Promise<void> {
const router = useRouter();
try {
const response = await service(data as T);
if (response.status === 'success') {
// 成功处理逻辑
if (handlePreset && presetHandler) {
await presetHandler();
}
if (successMessage) {
ElMessage.success(successMessage);
}
if (redirectTo) {
router.push(redirectTo);
}
onSuccess?.(response);
} else {
// 错误处理逻辑
if (Array.isArray(response.errors) && response.errors.length > 0) {
response.errors.forEach((error) => ElMessage.error(error));
} else {
ElMessage.error(response.message || errorMessage);
}
onError?.(response);
}
} catch (error) {
ElMessage.error(errorMessage);
onError?.(error);
}
}
提交示例
将提交逻辑抽象成通用工具函数调用:
import { handleRequest } from '@/utils/request';
import { serviceApply, servicePreset } from '@/services';
await handleRequest({
service: serviceApply.submit,
data: formData,
successMessage: '报名成功',
redirectTo: '/apply/progress',
handlePreset: saveAsPreset.value,
presetHandler: async () => {
const isDuplicate = presets.value.some(
(preset) => JSON.stringify(preset.data) === JSON.stringify(formData),
);
if (!isDuplicate) {
await servicePreset.create({ id: '', data: formData });
}
},
onSuccess: () => {
resetForm(true);
dialogVisible.value = false;
},
});
获取示例
将获取逻辑也通过通用工具封装:
import { handleRequest } from '@/utils/request';
import { serviceApply } from '@/services';
await handleRequest({
service: serviceApply.historyDetail,
data: record.memberkid,
successMessage: '', // 不需要成功提示
errorMessage: '无数据',
onSuccess: (response) => {
selectedRecord.value = response.data;
},
});
优势
- 减少重复代码:通用逻辑如成功、失败提示、异常捕获都已封装。
- 灵活可扩展:通过参数和回调函数,可以轻松调整行为。
- 提高可读性:每个页面的代码更简洁,逻辑聚焦于业务。
- 统一处理:例如可以在函数内部统一处理 API 错误格式变化,而不用修改各个页面代码。
扩展思路
- 全局错误处理:可引入错误监控工具,集中记录错误。
- 多语言支持:结合国际化库,如
vue-i18n
,动态调整消息内容。 - 类型强化:对
service
和response
增加更精确的类型推导,提高安全性。