我正在尝试使用以下代码将数据集合流式传输到多个文件:
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
对象中最后一个键的数组。看起来每个循环都会覆盖读取器流,并且在for循环结束之前,pipe()
到可写流不会启动。怎么可能?
答案 0 :(得分:1)
所以你编码的原因可能不起作用是因为rs._read方法是异步调用的,而你的键变量是函数作用域的(因为var关键字)。
您创建的每个rs流都指向同一个密钥变量,在主循环结束时,每个回调都将具有相同的值。 当你改变" var" to" let",然后在每次迭代中,将创建新的键变量,它将解决您的问题(_read函数将拥有自己的键变量副本而不是共享变量)。
如果你改变它让它应该工作。
答案 1 :(得分:0)
这种情况正在发生,因为您在循环语句中定义的key
不是块范围的。这首先不是问题,但是当你在rs._read
函数内部创建一个闭包时,所有后续流读取都使用最后一个已知值,这是data
数组的最后一个值。 / p>
虽然我们在此,我可以提出一些重构,以使代码更清晰,更可重用:
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));
}
});