fs.createReadStream循环处理多文件仅首个文件生效问题
问题根因
核心bug是全局复用了同一个csv-parse转换流实例:
- Node.js的流是单次使用的资源,第一个文件处理完成后,全局定义的
parser流已经触发end事件进入终止状态,后续无法再接收新数据、也不会再次触发data/end回调。 - 处理第二个文件时
fs.createReadStream实际已经执行,只是新的文件流被pipe到已经终止的parser上后,不会走任何解析和结束逻辑,对应的Promise一直挂起,代码就卡在这里不再往下执行,看起来像没读取第二个文件。
另外代码存在隐藏缺陷:没有监听fs.createReadStream本身的错误事件,一旦出现文件不存在、权限不足等问题,会直接抛出未捕获异常,不会进入你写的错误处理分支。
修复方案
- 移除全局的parser实例创建逻辑,每处理一个文件就初始化一个全新的csv-parse解析器,保证每个文件对应独立的、未被消费过的流链路。
- 补全读文件流的错误监听,所有错误场景都要触发Promise的
reject,避免Promise一直处于pending状态导致流程卡住。
修复后的可运行代码如下:
const fs = require('fs') const csv = require('csv-parse') const files = process.argv.slice(2) async function analyzeFiles () { for (const file of files) { console.log(`Analyzing ${file}.`) await runFile(file) console.log(`Analyzed ${file}.`) } } async function runFile (filepath) { return new Promise(function (resolve, reject) { const shimmedData = {} let fileName = '' let index = 0 // 补全原代码省略的索引变量,可按业务逻辑调整初始值 // 每次处理文件时新建独立的parser实例,保留原有解析配置即可 const parser = csv({ // 填写原代码里的csv解析配置 }) fs.createReadStream(filepath) .on('error', (e) => { // 捕获读文件阶段的错误 console.log('Read file error', e) reject(e) }) .pipe(parser) .on('data', (row) => { // 保留原有的行处理逻辑 fileName = 'something dynamic from row' shimmedData[index] = row index++ }) .on('error', (e) => { console.log('Parse csv error', e) reject(e) }) .on('end', () => { fs.writeFile(`${fileName}.json`, JSON.stringify(shimmedData), (err) => { if (err) { console.log('Write file error', err) reject(err) } else { console.log('File written successfully.') resolve() } }) }) }) } analyzeFiles()
修改后执行命令node script.js file1.txt file2.txt file3.txt,每个文件都会走独立的读流-解析-写文件流程,不会出现第二个文件卡住不处理的问题。
内容的提问来源于stack exchange,提问作者RichLitt
相关产品推荐
相关产品推荐

