React中文件下载等待异常求助:大文件未成功加入Zip包
解决Strapi批量下载PDF并生成Zip时未等待文件完成的问题
这个问题的核心是你在map里使用了异步函数,但map本身不会等待这些异步操作完成——它只会立刻返回一组Promise,而你通过判断索引来resolve的逻辑,其实只是确认遍历到了最后一个元素,而非所有文件都已经下载并写入Zip了,大文件因为下载耗时更长,这个问题就更明显。
修复方案:用Promise.all等待所有异步下载完成
把原来的map遍历换成Promise.all,它会等待所有传入的Promise都执行完成后才继续后续逻辑,这样就能确保所有PDF都下载并写入Zip后,再去生成最终的压缩包。
修改后的代码片段如下:
const downloadPdf = async (newData: any) => { return new Promise(async (resolve) => { let PolicyDocData: any; [...some operation...] if (newData.laws) { if (newData.laws.description[0]) { [...some operation to create an array for URL...] let lawDoc = Array.from(new Set(lawDocArray)); // 把每个下载任务包装成Promise,存入数组 const downloadTasks = lawDoc.map(async (val: any) => { const lawUrl = val.url.slice(1); const DocUrl = serverUrl + lawUrl; const response = await fetch(DocUrl, { method: "GET" }); const blob = await response.blob(); const fileType = ".pdf"; const timeStamp = Math.floor(Date.now() / 1000); const fileName = val.name; let docFileName = fileName + "_" + timeStamp; zip.folder("Compliance/Laws").file(docFileName + fileType, blob); }); // 等待所有下载和写入操作完成 await Promise.all(downloadTasks); // 现在所有文件都已就绪,可以resolve了 resolve(Contents); } } }).then((Contents: any) => { if (Contents) { Packer.toBlob(PolicyDocumentCreator(Contents)).then((blob) => { zip.generateAsync({ type: "blob" }).then(function (content: any) { saveAs(content, folderName ? folderName : complianceName + ".zip"); setLoading(false); }); }); } }); };
为什么原来的方式不行?
map遍历异步函数时,会一次性创建所有Promise并开始执行,但不会等待它们完成。你之前判断lawDoc.length - 1 === index时,只是说明循环到了最后一个元素,但这个元素对应的下载任务可能还在进行,前面的任务更不一定完成了。setTimeout是投机取巧的方式,你无法准确预估大文件的下载时间,设置短了还是会有问题,设置长了又会浪费用户时间,完全不符合异步编程的规范。
用Promise.all是最可靠的解决方案,它完美适配这种需要等待多个异步任务全部完成的场景。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

