如何使用JSZip同步生成zip文件?React循环触发下载异常求助
问题原因
- 变量声明问题:原代码使用
var声明循环变量j,var存在变量提升特性,无块级作用域,异步回调执行时获取的j是循环结束后的最终值,容易出现取值异常。 - 事件循环阻塞:仅在j=1和j=2000的分支使用了await阻塞逻辑,其余1998次循环都是同步执行,会瞬间跑完整个循环,全程阻塞浏览器事件循环,导致下载相关的异步回调被延后到所有同步代码执行完毕后才触发。
- 浏览器下载策略限制:短时间内连续触发多次下载,会被浏览器的安全策略拦截,统一延后到当前任务队列清空后执行。
修复方案
修改后的代码如下:
const generateCollection = async ()=>{ // 替换var为let,保证块级作用域,每个循环块拥有独立的j变量 for(let j = 1; j <= 2000; j++){ let zip = new JSZip(); let metadata = zip.folder("metadata"); const obj = {name: "Simple name", age: "Simple age"} metadata.file(`1.json`, JSON.stringify(obj, null, 4)) console.log("Start Downloading: ", j) if(j===1 || j===2000){ const content = await zip.generateAsync({type:"blob"}) setIsLoading(false) FileSaver.saveAs(content, `collection_${j}.zip`); console.log("Saved...... ", j) // 新增短延迟,避免连续下载被浏览器安全策略拦截 await new Promise(resolve => setTimeout(resolve, 100)) } else { // 非下载分支让出事件循环,避免同步代码阻塞下载任务执行 await Promise.resolve() } } }
修复说明
let替换var:确保每个循环迭代的j变量独立,不会出现异步回调获取到错误j值的问题。- 非下载分支加
await Promise.resolve():每次循环主动让出事件循环,让浏览器可以处理已经就绪的下载任务,不会被高密度的同步循环代码阻塞。 - 下载后加100ms延迟:给浏览器留出处理下载请求的时间,避免连续两次下载被安全策略合并拦截。
如果业务逻辑中j从2到1999的迭代没有其他必须执行的操作,也可以直接抽离j=1和j=2000的下载逻辑单独执行,不需要遍历完整2000次循环,性能会更好。
内容的提问来源于stack exchange,提问作者bilalo
相关产品推荐
相关产品推荐

