JavaScript:让处理函数等待异步CSV处理函数执行完成
问题分析与解决方案
你的问题根源在于removeFirstNRowsFromCsv是异步操作,但当前写法没有正确返回异步结果——FileReader的onload是回调函数,函数本身会立即返回undefined,根本等不到文件读取完成后的处理结果,才会导致后续dfd.readCSV报错。
第一步:改造removeFirstNRowsFromCsv返回Promise
将FileReader的异步逻辑包裹进Promise,在读取完成时返回处理后的File对象,同时处理读取失败的场景:
const removeFirstNRowsFromCsv = (csvFileRef, n) => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsText(csvFileRef); reader.onload = function() { const csvData = reader.result; const csvRows = csvData.split(/\r?\n|\r/); const csvRowsNew = csvRows.slice(n); // 用换行符拼接行,避免CSV格式混乱 const csvRowsNewString = csvRowsNew.join('\n'); const blob = new Blob([csvRowsNewString], { type: 'text/csv' }); const newFile = new File([blob], csvFileRef.name, { type: 'text/csv' }); resolve(newFile); }; // 捕获文件读取错误 reader.onerror = function() { reject(new Error(`读取文件 ${csvFileRef.name} 失败: ${reader.error}`)); }; }); }
第二步:改造handleUpload处理异步结果
根据需求选择两种处理方式:
方式1:按顺序处理文件(async/await + for...of)
确保前一个文件处理完成后再处理下一个:
const handleUpload = async (listOfFiles) => { for (const [index, file] of listOfFiles.entries()) { try { const processedFile = await removeFirstNRowsFromCsv(file, 6); const df = await dfd.readCSV(processedFile, { skipEmptyLines: true }); handleQa(df, processedFile, index); } catch (error) { console.error('文件处理出错:', error); } } }
方式2:并行处理所有文件(Promise.all)
无需按顺序时,用并行处理提高效率:
const handleUpload = (listOfFiles) => { const processPromises = listOfFiles.map(async (file, index) => { try { const processedFile = await removeFirstNRowsFromCsv(file, 6); const df = await dfd.readCSV(processedFile, { skipEmptyLines: true }); handleQa(df, processedFile, index); } catch (error) { console.error(`处理文件 ${file.name} 出错:`, error); } }); // 可选:等待所有文件处理完成后执行后续操作 Promise.all(processPromises).then(() => { console.log('所有文件处理完毕'); }); }
额外注意
- 原代码中
csvRowsNew.join('')会导致行之间丢失换行符,破坏CSV格式,必须改成join('\n')。 - 必须添加错误捕获逻辑,避免出现未处理的Promise异常。
内容的提问来源于stack exchange,提问作者jmelm93
相关产品推荐
相关产品推荐

