如何优化含文件上传的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
相关产品推荐
相关产品推荐

