JavaScript全局数组在事件间数据丢失问题求助
问题根源与解决方案
1. 核心问题:变量重声明覆盖外层作用域
在$('#fileInput').on('change')事件处理函数内部,你重新声明了var fileListProperty = [];,这会创建一个局部变量,完全覆盖了$(document).ready作用域下的同名数组。也就是说,你在change事件里填充的是这个局部数组,而外层的目标数组始终是空的,所以点击提交按钮时访问的自然是空数组。
修复方法:删除change事件内部的var fileListProperty = [];,直接清空外层作用域的数组(避免多次选择文件时数据累积):
// 在change事件内,替换原来的var声明 fileListProperty = []; // 直接操作外层数组,不要加var
2. 其他潜在问题修复
(1) Promise参数传递错误
Promise的resolve和reject只能传递一个参数,你现在传了两个参数resolve(file.name, index),第二个参数会被直接忽略。需要把参数包装成对象传递:
// 修正resolve/reject调用 resolve({ fileName: file.name, index: index }); reject({ fileName: file.name, index: index }); // 对应then回调也要修改 onLoadPromise.then( (result) => { const { fileName, index: zeIndex } = result; // 后续逻辑不变 }, (error) => { const { fileName, index: zeIndex } = error; // 后续逻辑不变 } )
(2) 变量拼写错误
在非PP7文件的处理分支里,你写的是nbFile++,但前面声明的计数变量是nbFiles,这会导致计数错误,修改为:
nbFiles++;
(3) 提交事件重复绑定问题
每次点击提交按钮时,你都会重新绑定$('#pp7Form').submit事件,这会导致事件被多次绑定,后续提交会触发多次回调。应该把提交事件绑定移到$(document).ready的顶层:
// 在ready顶层绑定一次提交事件 $(document).ready(() => { // ...其他代码 $('#pp7Form').submit((evt) => { if ($("#fileInput").prop("files").length === 0) { evt.preventDefault(); return; } $("#pp7Form").ajaxSubmit(); return false; }); // 提交按钮的click事件只处理进度查询逻辑 $("#btnSubmit").on('click', () => { if ($("#fileInput").prop("files").length === 0) return; // 进度查询逻辑... }); });
(4) 异步轮询的死循环问题
你用while (nbFilecompleted < nbValidFile)来循环查询进度,但$.post是异步操作,while会在异步请求返回前无限执行,直接导致浏览器卡死。改用递归+setTimeout实现轮询:
// 替换原来的while循环 var nbValidFile = fileListProperty.filter(element => element.valid).length; var nbFilecompleted = 0; const checkProgress = () => { if (nbFilecompleted >= nbValidFile) return; let hasPending = false; fileListProperty.forEach((file, idx) => { if (file.valid && file.pctConversion < 100) { hasPending = true; $.post('https://ol-portal-dev-nr.ca.objectiflune.com/getStat', { UUID: $("#uuid").val(), fileID: file.fileIndex }, (data, status, xhr) => { if (status === 'success') { const percentage = JSON.parse(data).percentage; file.pctConversion = percentage; if (percentage === 100) nbFilecompleted++; } else { alert('An error has occurred, please contact jhamel@uplandsoftware.com'); } }); } }); if (hasPending) setTimeout(checkProgress, 500); }; checkProgress(); // 启动轮询
最终修复后的关键代码片段
$(document).ready(() => { var fileListProperty = []; $("#loaderContainer").hide(); $("#browseBtn").on('click', () => { $('#btnSubmit').addClass("btnSubmitDisabled"); $("#formList").empty(); $('#fileInput').click(); }); $('#fileInput').on('change', () => { $("#loaderContainer").show(); var files = $("#fileInput").prop("files"); var fileListValid = false; fileListProperty = []; // 清空外层数组 var nbFiles = 0; const dt = new DataTransfer(); Array.from(files).forEach((file, index) => { if (file.name.indexOf(".pp7") >= 0) { let onLoadPromise = new Promise((resolve, reject) => { let reader = new FileReader(); reader.onloadend = (evt) => { let fileContent = evt.target.result; if (fileContent.substr(0, 2) === "PK") { resolve({ fileName: file.name, index: index }); } else { reject({ fileName: file.name, index: index }); } } reader.readAsText(file); }); onLoadPromise.then( (result) => { const { fileName, index: zeIndex } = result; dt.items.add(file); fileListProperty.push({ fileIndex: zeIndex, fileName: file.name, valid: true, message: "Valid PP7 file.", pctConversion: 0 }); }, (error) => { const { fileName, index: zeIndex } = error; fileListProperty.push({ fileIndex: zeIndex, fileName: file.name, valid: false, message: fileName + " isn't a valid PP7 file. Cannot be converted.", pctConversion: 0 }); } ).finally(() => { nbFiles++; if (nbFiles === files.length) DisplayFileList(); }); } else { fileListProperty.push({ fileIndex: index, fileName: file.name, valid: false, message: file.name + " isn't a valid PP7 file. Cannot be converted.", pctConversion: 0 }); nbFiles++; if (nbFiles === files.length) DisplayFileList(); } }); var DisplayFileList = () => { fileListValid = false; fileListProperty.forEach((propJSON) => { if (propJSON.valid) fileListValid = true; }); $("#fileInput").prop("files", dt.files); $("#loaderContainer").delay(1500).hide(0, () => { BuildFormList(); if (fileListValid) { $('#btnSubmit').removeClass("btnSubmitDisabled"); } }); } var BuildFormList = () => { $("#formList").empty(); fileListProperty.forEach((listProperty) => { $("#formList").append( `<div class="fileContainer" idx="${listProperty.fileIndex}">` + ` <div class="fileName">${listProperty.fileName}</div>` + ` <div class="fileMessage ${listProperty.valid ? 'valid' : 'error'}">${listProperty.message}</div>` + `</div >`); }); } }); $('#pp7Form').submit((evt) => { if ($("#fileInput").prop("files").length === 0) { evt.preventDefault(); return; } $("#pp7Form").ajaxSubmit(); return false; }); $("#btnSubmit").on('click', () => { if ($("#fileInput").prop("files").length === 0) return; var nbFilecompleted = 0; var nbValidFile = fileListProperty.filter(element => element.valid).length; const checkProgress = () => { if (nbFilecompleted >= nbValidFile) return; let hasPending = false; fileListProperty.forEach((file, idx) => { if (file.valid && file.pctConversion < 100) { hasPending = true; $.post('https://ol-portal-dev-nr.ca.objectiflune.com/getStat', { UUID: $("#uuid").val(), fileID: file.fileIndex }, (data, status, xhr) => { if (status === 'success') { const percentage = JSON.parse(data).percentage; file.pctConversion = percentage; if (percentage === 100) nbFilecompleted++; } else { alert('An error has occurred, please contact jhamel@uplandsoftware.com'); } }); } }); if (hasPending) setTimeout(checkProgress, 500); }; checkProgress(); }); });
内容的提问来源于stack exchange,提问作者Jean-Cédric Hamel
相关产品推荐
相关产品推荐

