记录前端菜鸟的日常——element-upload多文件上传顺序挑战
上周的一个问题,业务说同时选中三张图片上传,保存之后再查看发现跟她选中的顺序不一致
我看了一下是前端返回给后端的图片数组的顺序就已经不对了,说明在每次上传的那个upload接口顺序也不对,最开始代码里写的是:auto-upload="true",每次点击就自动调用upload接口(一张一张传的话就没问题)
搜了一下乱序是因为:
- 图片大小原因
- 并发请求导致乱序
- 响应时间也不一定
我最开始的想法是利用el-upload里的那个on-change,每次变化都能记录当时的文件和所有文件的数组(后来发现这个数组实际内容跟console的不一样),把这个二进制文件的.raw push到新数组中,这个顺序是对着的,然后我把这个二进制文件的数组一个一个去掉后端接口,最后把图片链接的数组传给后端,这个想法当时我觉得没问题,我就开始做了
最开始我用的async和await去处理异步,等待接口返回结果之后再进行下一轮循环,搭配了for循环(forEach不等待异步)
changeFile(file, fileList) {
console.log('调用几次?')
console.log(fileList, 'fileList')
// 符合条件的进入待传列表
this.upFileList = fileList.map(x => x.raw);
console.log(this.upFileList, 'upFileList')
this.submitUpload2();
}
但是用这种方法怎么都不对,我一直以为是for循环那边的问题,接口还没来得及返回结果就进入到了下一轮循环,后来我发现onChange的那个数组也有问题,一次性上传3个文件之后fileList输出三个文件,但是fileList的length却是依次1=>2=>3,说明这个fileList输出出来的跟实际的不太一样,问了一下chat
fileList.length返回的是 当前已通过验证的文件数控制台展开显示的是 最终会包含的所有文件(但此时还未全部验证完成)
发现是这个on-change不对之后我就放弃了把每次的文件单独放到一个新数组中再掉接口(因为每次不能拿到全部图片的数组,而且掉接口的时机不好整),直接在onchange里每次变化就掉接口的话就是最开始的样子,并发执行顺序不对
然后我就想写一个队列出来,用一个flag记录当时的队列有没有在进行的内容,没有的话再推入到队列中
// 宣传画廊图片变化
changeFile(file) {
console.log('change', file)
this.uploadQueue.push(file.raw); // 加入队列
if (!this.isUploading) {
this.processQueue();
}
},
// 队列
async processQueue() {
if (this.uploadQueue.length === 0) return;
this.isUploading = true;
const file = this.uploadQueue.shift(); // 取出第一个文件
await this.submitUpload2(file); // 等待上传完成
this.isUploading = false;
this.processQueue(); // 处理下一个
},
// 正式上传掉后端接口
async submitUpload2(file) {
const formData = new FormData();
formData.append('file', file);
formData.append('name', file.name);
try {
const res = await fileUpload(formData);
if (res.code === 200) {
// 找到对应的file对象并更新response
const targetFile = this.$refs.upload.uploadFiles.find(
f => f.uid === file.uid || f.name === file.name
);
if (targetFile) {
targetFile.response = { data: res.data };
}
this.goods.gallery.push(res.data);
}
return res.code === 200;
} catch (error) {
this.$message.error(`${file.name} 上传错误,请重新上传`);
this.removeFailedFile(file); // 关键:移除失败文件
return false;
}
},
最后将上传失败的图片移除
// 移除失败文件
removeFailedFile(file) {
// 从upload组件中移除
const fileList = this.$refs.upload.uploadFiles;
const index = fileList.findIndex(f => f.uid === file.uid);
if (index !== -1) {
fileList.splice(index, 1);
}
// 从本地队列中移除(如果有)
const queueIndex = this.uploadQueue.findIndex(f => f.name === file.name);
if (queueIndex !== -1) {
this.uploadQueue.splice(queueIndex, 1);
}
},
浙公网安备 33010602011771号