You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化含文件上传的Ajax流程,避免重复跳转(遵循DRY原则)

问题

我有一个带文件上传字段的标准表单,通过Ajax处理表单提交。处理成功的回调里,有文件的话要发起另一个Ajax请求上传文件,成功后跳转;没文件就直接跳转。不想重复写跳转逻辑,虽然知道可以封装成函数调用,但想找更简洁的写法,符合DRY原则。

原代码如下:

if (files.length > 0) {
  readFile(files[0],function(filestring){
    var fileObj = new Object();
        fileObj.file = filestring.split(";;base64,")[1];
        fileObj.fullFileName = document.getElementById("file").files[0].name;
        fileObj.fileName = fileObj.fullFileName.split(".")[0];
        fileObj.ext = fileObj.fullFileName.split(".")[1];
        fileObj.leadid = resp.leadid;

        doAjax(fileObj,endpoints.file).then(function(resp){
          window.location.href = "returnURL";
        });
  });              
}else{
    window.location.href = "returnURL";
}

附doAjax函数:

function doAjax(data,url){
  return  $.ajax({
            url: url,
            cache: false,
            method: "post",
            dataType:"json",
            data: data
        });
}

附readFile函数:

function readFile(files,callback){
  var reader = new FileReader();
  reader.readAsDataURL(files);
  reader.onload = function (e) {
    callback(reader.result);
  }
  reader.onerror = function (error) {
      console.log('Error: ', error);
  };  
}
解决方案

我们可以借助Promise链式调用来统一逻辑,把文件处理流程封装为Promise,无论是否存在文件,最终都通过同一个then分支执行跳转,彻底消除重复代码:

1. 改造readFile为Promise风格

首先把依赖回调的readFile改成返回Promise的版本,方便后续链式调用:

function readFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => {
      console.log('Error: ', error);
      reject(error);
    };
  });
}

2. 重构主逻辑

然后将原有的分支逻辑整合为统一的Promise链:

// 初始化一个已完成的Promise,对应无文件场景
let processing = Promise.resolve();

if (files.length > 0) {
  // 有文件时,替换为文件读取+上传的Promise流程
  processing = readFile(files[0])
    .then(filestring => {
      const fullFileName = files[0].name; // 直接用files[0],避免重复DOM查询
      const [fileName, ext] = fullFileName.split(".");
      const fileObj = {
        file: filestring.split(";;base64,")[1],
        fullFileName,
        fileName,
        ext,
        leadid: resp.leadid
      };
      return doAjax(fileObj, endpoints.file);
    });
}

// 统一执行跳转逻辑
processing.then(() => {
  window.location.href = "returnURL";
});

核心思路

  • 用一个基础Promise覆盖无文件的情况,有文件时则替换为完整的文件处理Promise链
  • 所有场景最终都通过同一个then执行跳转,完全消除重复代码
  • 用解构赋值简化文件名拆分逻辑,同时用files[0]替代重复的DOM查询,优化性能

内容的提问来源于stack exchange,提问作者Stan Alachniewicz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:55:22