如何用async/await实现ngx-file-drop多图顺序上传并传递post_id参数
多图按顺序上传需求及解决方法
需求背景
- 使用ngx-file-drop组件实现拖拽多图上传功能
- 需要通过async/await实现图片按顺序上传,首个请求返回的
post_id要作为参数携带在后续所有图片的上传请求中
现存问题
现有实现不会等待上一个上传请求完成就发起下一个请求,无法满足post_id的传递要求,原有实现代码如下:
dropped(files: NgxFileDropEntry[]) { this.files = files; for (const droppedFile of files) { // 判断是否为文件 if (droppedFile.fileEntry.isFile) { const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; fileEntry.file(async (file: File) => { // 此处可获取到真实文件对象 console.log(droppedFile.relativePath, file); await new Promise((resolve, reject) => { this.http.uploadImages(file, 'UploadImage', this.postId).subscribe((res: any) => { if (res.status == true) { resolve(true); this.postId = res.data.post_id; // 期望将这个ID传递到下一个请求 } else { reject(); console.log(res.message); } }) }); }); } else { // 为目录时的逻辑(空目录也会被纳入,否则仅处理文件) const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry; console.log(droppedFile.relativePath, fileEntry); } } }
问题根因
原有代码中fileEntry.file()的回调为异步执行,循环不会等待回调内的Promise完成就会处理下一个文件,因此请求会并发发出,post_id无法按预期顺序传递。
修复后代码
// 先将FileEntry转File的回调逻辑封装为Promise,方便后续await调用 private getFileFromEntry(fileEntry: FileSystemFileEntry): Promise<File> { return new Promise((resolve) => { fileEntry.file((file) => resolve(file)); }); } async dropped(files: NgxFileDropEntry[]) { this.files = files; // 先筛选出所有需要上传的文件,排除目录项 const fileEntries = files .filter(f => f.fileEntry.isFile) .map(f => f.fileEntry as FileSystemFileEntry); // 按顺序循环处理每个文件,await等待上一个上传完成后再处理下一个 for (const entry of fileEntries) { const file = await this.getFileFromEntry(entry); // 上传逻辑,等待当前上传完成后才会进入下一次循环 await new Promise((resolve, reject) => { this.http.uploadImages(file, 'UploadImage', this.postId).subscribe((res: any) => { if (res.status == true) { this.postId = res.data.post_id; resolve(true); } else { console.log(res.message); reject(res.message); // 若出错后需要中断后续上传保留此处reject即可;若需要继续上传可改为resolve,按业务需求调整即可 } }); }); } }
实现说明
- 提前筛选所有需要上传的文件,避免循环中处理目录逻辑干扰异步执行顺序
- 把
fileEntry.file()的回调逻辑封装为Promise后,就可以在循环中用await等待获取到文件再执行上传 - for...of循环搭配await会严格按顺序执行,上一个文件上传完成、postId更新后才会处理下一个文件,完全满足需求
内容的提问来源于stack exchange,提问作者Najam Us Saqib
相关产品推荐
相关产品推荐

