使用try-finally结构执行状态重置

原代码

const commitForm = async () => {
  btnLoading.value = true;
  isCommitted.value = true;
  //过滤出显示字段的列表
  let showFieldsList = [];
  for (let comp of compList.value) {
    if (comp.isShow) {
      showFieldsList.push(comp);
    }
  }

  //必填校验
  for (let comp of showFieldsList) {
    if (comp.isRequired && comp.isShow) {
      if (comp.type === "showPic") {
        if (comp.picUrl) {
          formData.value[comp.prop] = comp.picUrl;
        }
      } else if (comp.type === "subForm") {
        const subForm = comp.subForm;
        if (subForm) {
          // 子表单必填字段列表
          let propList = [];
          for (let subComp of subForm) {
            if (subComp.isConfigRequired) {
              propList.push({
                prop: subComp.prop,
                label: subComp.label,
              });
            }
          }
          const subFormFillDataStr = formData.value[comp.prop];
          const subFormFillDataArr = JSON.parse(subFormFillDataStr ?? "[]");
          if (subFormFillDataArr.length === 0 && propList.length > 0) {
            message.error(`请填写子表单数据`);
            return;
          }
          for (let item of propList) {
            for (let subFormFillData of subFormFillDataArr) {
              if ((subFormFillData[item.prop] ?? "") === "") {
                message.warning(`${item.label}是必填字段`);
                return;
              }
            }
          }
        }
      } else if (comp.type === "checkBox") {
        if (
          formData.value[comp.prop] == "others" ||
          (Array.isArray(formData.value[comp.prop]) &&
            formData.value[comp.prop].length === 0) ||
          (formData.value[comp.prop] ?? "") === ""
        ) {
          message.warning(`${comp.label}是必填字段`);
          return;
        }

        if (
          formData.value[comp.prop].includes("others") &&
          !formData.value[comp.prop].some((item) => item.startsWith("others-"))
        ) {
          message.warning(`${comp.label}字段的其他选项勾选但未填写`);
          return;
        }
      } else if ((formData.value[comp.prop] ?? "") === "") {
        message.warning(`${comp.label}是必填字段`);
        return;
      }

      //校验手机号
      if (comp.isValidateTel) {
        if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(comp.sensitiveInfoTxt)) {
          message.warning(`${comp.label}格式错误`);
          return;
        }
      }

      // 正则表达式校验
      if (comp.regExp && comp.regExp !== "") {
        const res = validateCompValue(comp);
        if (!res) {
          return;
        }
      }

      //相等校验
      if (comp.sameValueAsCompValue) {
        if (
          formData.value[comp.prop] !==
          formData.value[comp.sameValueAsCompValue]
        ) {
          message.warning(`${comp.label}字段配置的两次输入内容不同`);
          return;
        }
      }
    }
  }

  const copyFormState = JSON.parse(JSON.stringify(formData.value));
  for (let comp of compList.value) {
    if (["checkBox", "dataBind"].includes(comp.type)) {
      if (Array.isArray(copyFormState[comp.prop])) {
        copyFormState[comp.prop] = copyFormState[comp.prop].join(",");
        copyFormState[comp.prop] = rearrangeOthers(copyFormState[comp.prop]);
      }
    }

    if (comp.type === "dateTime") {
      if (copyFormState[comp.prop]) {
        copyFormState[comp.prop] = dayjs(copyFormState[comp.prop]).format(
          "YYYY-MM-DD HH:mm"
        );
      }
    }
  }

  const res = await validateTryUpdateOrder(
    props.workConfCode,
    props.formWebUuid
  );

  if (res === "covered") {
    return;
  }

  const params = {
    workConfCode: props.workConfCode,
    parentOrderId: route.query.orderId,
    subFormWebUuid: props.formWebUuid,
  };
  SmartFormApi.subFormNewRecord(params, copyFormState)
    .then(async (result) => {
      if (result.data.code === 200) {
        message.success("已提交表单");
        emit("updateFormStatus", "已完成");
      } else {
        message.error(result.data.message);
        btnLoading.value = false;
        isCommitted.value = false;
      }
    })
    .catch((err) => {
      console.error(err);
      btnLoading.value = false;
      isCommitted.value = false;
    });
};

需要一进入这个函数就给按钮置灰,防止重复提交,但是函数内部return很多。

如果给每个return前都加上恢复按钮正常功能,则会造成大量的工作量和代码冗余,且不利于后续扩展。

可以使用try-finally结构,将代码改为

const commitForm = async () => {
  btnLoading.value = true;
  isCommitted.value = true;
  
  try {
    //过滤出显示字段的列表
    let showFieldsList = [];
    for (let comp of compList.value) {
      if (comp.isShow) {
        showFieldsList.push(comp);
      }
    }

    //必填校验
    for (let comp of showFieldsList) {
      if (comp.isRequired && comp.isShow) {
        if (comp.type === "showPic") {
          if (comp.picUrl) {
            formData.value[comp.prop] = comp.picUrl;
          }
        } else if (comp.type === "subForm") {
          const subForm = comp.subForm;
          if (subForm) {
            // 子表单必填字段列表
            let propList = [];
            for (let subComp of subForm) {
              if (subComp.isConfigRequired) {
                propList.push({
                  prop: subComp.prop,
                  label: subComp.label,
                });
              }
            }
            const subFormFillDataStr = formData.value[comp.prop];
            const subFormFillDataArr = JSON.parse(subFormFillDataStr ?? "[]");
            if (subFormFillDataArr.length === 0 && propList.length > 0) {
              message.error(`请填写子表单数据`);
              return; // 校验失败,退出执行
            }
            for (let item of propList) {
              for (let subFormFillData of subFormFillDataArr) {
                if ((subFormFillData[item.prop] ?? "") === "") {
                  message.warning(`${item.label}是必填字段`);
                  return; // 校验失败,退出执行
                }
              }
            }
          }
        } else if (comp.type === "checkBox") {
          if (
            formData.value[comp.prop] == "others" ||
            (Array.isArray(formData.value[comp.prop]) &&
              formData.value[comp.prop].length === 0) ||
            (formData.value[comp.prop] ?? "") === ""
          ) {
            message.warning(`${comp.label}是必填字段`);
            return; // 校验失败,退出执行
          }

          if (
            formData.value[comp.prop].includes("others") &&
            !formData.value[comp.prop].some((item) => item.startsWith("others-"))
          ) {
            message.warning(`${comp.label}字段的其他选项勾选但未填写`);
            return; // 校验失败,退出执行
          }
        } else if ((formData.value[comp.prop] ?? "") === "") {
          message.warning(`${comp.label}是必填字段`);
          return; // 校验失败,退出执行
        }

        //校验手机号
        if (comp.isValidateTel) {
          if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(comp.sensitiveInfoTxt)) {
            message.warning(`${comp.label}格式错误`);
            return; // 校验失败,退出执行
          }
        }

        // 正则表达式校验
        if (comp.regExp && comp.regExp !== "") {
          const res = validateCompValue(comp);
          if (!res) {
            return; // 校验失败,退出执行
          }
        }

        //相等校验
        if (comp.sameValueAsCompValue) {
          if (
            formData.value[comp.prop] !==
            formData.value[comp.sameValueAsCompValue]
          ) {
            message.warning(`${comp.label}字段配置的两次输入内容不同`);
            return; // 校验失败,退出执行
          }
        }
      }
    }

    const copyFormState = JSON.parse(JSON.stringify(formData.value));
    for (let comp of compList.value) {
      if (["checkBox", "dataBind"].includes(comp.type)) {
        if (Array.isArray(copyFormState[comp.prop])) {
          copyFormState[comp.prop] = copyFormState[comp.prop].join(",");
          copyFormState[comp.prop] = rearrangeOthers(copyFormState[comp.prop]);
        }
      }

      if (comp.type === "dateTime") {
        if (copyFormState[comp.prop]) {
          copyFormState[comp.prop] = dayjs(copyFormState[comp.prop]).format(
            "YYYY-MM-DD HH:mm"
          );
        }
      }
    }

    const res = await validateTryUpdateOrder(
      props.workConfCode,
      props.formWebUuid
    );

    if (res === "covered") {
      return; // 校验失败,退出执行
    }

    const params = {
      workConfCode: props.workConfCode,
      parentOrderId: route.query.orderId,
      subFormWebUuid: props.formWebUuid,
    };
    await SmartFormApi.subFormNewRecord(params, copyFormState)
      .then((result) => {
        if (result.data.code === 200) {
          message.success("已提交表单");
          emit("updateFormStatus", "已完成");
        } else {
          message.error(result.data.message);
          // 接口返回错误,需要重置状态
          throw new Error(result.data.message);
        }
      });
  } catch (err) {
    console.error(err);
  } finally {
    // 无论成功失败,最终都重置状态
    btnLoading.value = false;
    isCommitted.value = false;
  }
};

主要优化点说明:

1. 使用 try-finally 结构,确保在任何情况下(包括所有 return 点)都会执行状态重置

2. 将所有校验失败的情况通过 return 退出,最终都会走到 finally 块

3. 接口调用失败时通过 throw new Error 触发 catch 块,最终也会走到 finally 块

4. 成功提交后仍然会执行 finally 块重置状态,这符合业务逻辑

这样修改后,不需要在每个 return 前都写状态重置的代码,既减少了重复代码,也避免了遗漏重置状态的情况。
 
posted @ 2025-09-22 22:44  罗毅豪  阅读(6)  评论(0)    收藏  举报