使用JSZip时循环调用async异步函数如何正确获取返回数据
问题核心原因
- 你定义的
waitStr是异步函数,调用后不会阻塞主程序执行,循环里触发的所有文件读取任务还没完成时,主程序后续的代码就已经执行了,所以读取fileToFind返回undefined - 循环内的异步逻辑如果直接嵌入主程序代码,确实会触发多次执行,所以需要统一等待所有异步任务结束后再一次性执行主逻辑
修正方案
我们可以把所有文件的读取任务都封装成Promise,统一等待全部执行完成后筛选出目标文件内容,再执行后续主逻辑:
// 存放所有文件读取的异步任务 const fileReadTasks = []; const anchorStr = "Some string which is in only one file"; JSZip.forEach(function (relativePath, file){ // 把每个文件的读取和匹配逻辑都封装成Promise,加入任务队列 const task = JSZip.file(relativePath).async("string").then(fileContent => { // 匹配到目标文件就返回内容,没匹配到返回null return fileContent.includes(anchorStr) ? fileContent : null; }); fileReadTasks.push(task); }); // 等待所有文件读取任务完成,筛选出目标文件内容 Promise.all(fileReadTasks).then(results => { // 过滤掉所有null结果,拿到唯一的目标文件内容 const fileToFind = results.find(content => content !== null); console.log(fileToFind); // 可以正常拿到内容 // 你的后续主程序逻辑全部放在这里执行,只会执行一次 // ... 原来的lot of stuff 逻辑都挪到这 });
补充说明
如果你的zip包文件很多,也可以用Promise.any提前终止等待,只要匹配到第一个符合条件的文件就直接返回结果,不需要等所有文件读取完成,性能更好。如果习惯用async/await的写法,也可以把外层逻辑包裹在一个async函数里,用await替代then的写法,代码可读性更高:
async function getTargetFileContent(zipInstance) { const anchorStr = "Some string which is in only one file"; const fileReadTasks = []; zipInstance.forEach((relativePath, file) => { fileReadTasks.push(zipInstance.file(relativePath).async("string")); }); const allContents = await Promise.all(fileReadTasks); return allContents.find(content => content.includes(anchorStr)); } // 调用示例 async function main() { // 这里替换成你自己的JSZip实例加载逻辑 const zip = await JSZip.loadAsync(/* 你的zip文件数据 */); const fileToFind = await getTargetFileContent(zip); console.log(fileToFind); // 后续主程序逻辑 // ... lot of stuff } main();
内容的提问来源于stack exchange,提问作者PaddleStroke
相关产品推荐
相关产品推荐

