Vue3 通用请求工具函数:高效封装提交与获取逻辑,告别重复代码

在这里插入图片描述

问题

大量的页面都实现了类似的代码

//提交类
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('请求失败,请稍后重试'); 
}

是不是应该有一个函数或工具,能实现这些类似的功能?当然,必须所有参数都可在这个函数工具里设置,也可以就用默认的。

方案

为了减少代码重复,并使逻辑更加清晰和可维护,可以创建一个通用的工具函数来封装这些操作。这种函数不仅可以简化提交和获取数据的流程,还可以提供可配置的默认参数,同时允许在必要时覆盖默认行为。

以下是一个可能的实现思路:


通用工具函数设计

  1. 封装 HTTP 请求:处理请求、响应、错误、成功和失败的逻辑。
  2. 提供默认参数:如是否显示消息提示、成功后的回调、失败后的回调等。
  3. 允许覆盖行为:支持传递额外配置,动态调整行为。
通用函数实现
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;
  },
});

优势

  1. 减少重复代码:通用逻辑如成功、失败提示、异常捕获都已封装。
  2. 灵活可扩展:通过参数和回调函数,可以轻松调整行为。
  3. 提高可读性:每个页面的代码更简洁,逻辑聚焦于业务。
  4. 统一处理:例如可以在函数内部统一处理 API 错误格式变化,而不用修改各个页面代码。

扩展思路

  • 全局错误处理:可引入错误监控工具,集中记录错误。
  • 多语言支持:结合国际化库,如 vue-i18n,动态调整消息内容。
  • 类型强化:对 serviceresponse 增加更精确的类型推导,提高安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值