Node – 可读streamstream()覆盖for循环中的前一个stream

我正在尝试使用以下代码将数据集合stream式传输到多个文件:

for (var key in data) { // skip if collection length is 0 if (data[key].length > 0) { // Use the key and jobId to open file for appending let filePath = folderPath + '/' + key + '_' + jobId + '.txt'; // Using stream to append the data output to file, which should perform better when file gets big let rs = new Readable(); let n = data[key].length; let i = 0; rs._read = function () { rs.push(data[key][i++]); if (i === n) { rs.push(null); } }; rs.pipe(fs.createWriteStream(filePath, {flags: 'a', encoding: 'utf-8'})); } } 

但是,我最终得到的所有文件都被填充了相同的数据,这是data对象中最后一个键的数组。 看起来,每个循环都会覆盖读取器stream,直到for循环完成, pipe()才能写入stream。 这怎么可能?

所以你的代码可能不工作的原因是因为rs._read方法是asynchronous调用的,而你的关键variables是函数作用域(因为var关键字)。

您创build的每个rsstream都指向相同的variables,在主循环结束时,每个callback将具有相同的值。 当你把“var”改成“let”,那么在每次迭代中,将会创build一个新的键variables,它将解决你的问题(_read函数将拥有自己的键variables副本,而不是共享副本)。

如果你改变它,让它应该工作。

发生这种情况是因为在循环语句中定义的key不是块范围的。 这不是一个问题,但是当你在rs._read函数中创build一个闭包时,所有后续的stream读操作都使用最后一个已知的值,这是data数组的最后一个值。

虽然我们可以提出一些重构来使代码更清洁,更可重用:

 const writeStream = (folderPath, index, jobId) => { const filePath = `${folderPath}/${index}_${jobId}.txt`; return fs.createWriteStream(filePath, { flags: 'a', encoding: 'utf-8' }); } data.forEach((value, index) => { const length = value.length; if (length > 0) { const rs = new Readable(); const n = length; let i = 0; rs._read = () => { rs.push(value[i++]); if (i === n) rs.push(null); } rs.pipe(writeStream(folderPath, index, jobId)); } });