使用Compressor JS压缩多图时无法将结果追加至FormData对象
异常核心成因
两类异常的触发逻辑完全同源:Compressor JS的图片压缩为异步执行流程,success回调的触发时机远晚于外层同步代码的执行阶段。
- 感知到
fd.append无实际效果的本质:循环逻辑执行时,仅完成了每个文件的压缩任务注册,同步流程走到发起上传的节点时,所有压缩回调都还没触发,此时的FormData对象本身是空的。等后续回调真正执行append操作时,上传请求已经携带空FormData发送完成,自然感知不到append的作用。 - 数组读取异常的本质:浏览器控制台打印对象/数组时,存储的是对内存地址的引用,而非打印时刻的内容快照。同步代码执行阶段打印数组时,数组本身无值,但后续异步回调将压缩结果push进数组后,控制台展示的引用会同步更新为最新状态;如果在同步执行阶段直接通过下标读取数组元素,因push操作尚未执行,必然返回undefined。
正确实现方案
将单个文件的压缩逻辑封装为Promise实例,通过Promise.all等待所有文件压缩完成后,再统一组装FormData对象发起上传,避免异步时序导致的操作失效问题。
示例代码:
// 封装单文件压缩的Promise实例 function compressImage(file) { return new Promise((resolve, reject) => { new Compressor(file, { quality: 0.4, maxWidth: 800, success: resolve, error: reject }) }) } // 上传流程需放在async函数中执行 async function startUpload() { const fileList = Array.from(document.querySelector('[type=file]').files); // 等待所有文件完成压缩 const compressedFiles = await Promise.all( fileList.map(file => compressImage(file)) ) // 所有压缩结果返回后再组装FormData const fd = new FormData(); compressedFiles.forEach(file => { // 多图上传使用同名key追加,后端可直接按数组接收 fd.append('compressedImage', file, file.name) }) // 此时fd已携带全部压缩后文件,可正常发起上传请求 // 示例:fetch('/upload', { method: 'POST', body: fd }) }
验证小提示:如果需要确认异步流程的执行结果,打印数组时可使用深拷贝生成快照,例如
console.log([...compressedImgs]),避免控制台引用更新带来的认知偏差。
内容的提问来源于stack exchange,提问作者Grosu Cristi-Alexandru
相关产品推荐
相关产品推荐

