Javascript 使用fs.createWriteStream在Nodejs中写入大文件

Javascript 使用fs.createWriteStream在Nodejs中写入大文件,javascript,node.js,Javascript,Node.js,我有一个函数,在完美世界中应该创建一个巨大的1M行文件。这是: const fileWriteStream = fs.createWriteStream(path.resolve(filePath)); let ableToWrite = true; for (let i = 0; i < 1e6; i++) { if (ableToWrite) { ableToWrite = fileWriteStream.write(`.

我有一个函数,在完美世界中应该创建一个巨大的1M行文件。这是:

    const fileWriteStream = fs.createWriteStream(path.resolve(filePath));
    let ableToWrite = true;
    for (let i = 0; i < 1e6; i++) {
        if (ableToWrite) {
            ableToWrite = fileWriteStream.write(`.testClass${itr}-${i%2} { background: red } \n`);
        } else {
            fileWriteStream.once('drain', () => {
                ableToWrite = fileWriteStream.write(`.testClass${itr}-${i%2} { background: red } \n`);
            })
        }
    }
我真的不想增加此函数的侦听器数。 使用streams编写如此大的文件的正确方法是什么


非常感谢

流耗尽时异步继续的最简单方法是在循环中使用
wait
,并承诺:

const fileWriteStream = fs.createWriteStream(path.resolve(filePath));
for (let i = 0; i < 1e6; i++) {
    const ableToWrite = fileWriteStream.write(`.testClass${itr}-${i%2} { background: red } \n`);
    if (!ableToWrite) {
        await new Promise(resolve => {
            fileWriteStream.once('drain', resolve);
        });
    }
}

流耗尽时异步继续的最简单方法是在循环中使用
wait
,并承诺:

const fileWriteStream = fs.createWriteStream(path.resolve(filePath));
for (let i = 0; i < 1e6; i++) {
    const ableToWrite = fileWriteStream.write(`.testClass${itr}-${i%2} { background: red } \n`);
    if (!ableToWrite) {
        await new Promise(resolve => {
            fileWriteStream.once('drain', resolve);
        });
    }
}

您将需要另一种流控制方法:递归函数、生成器等。您是否理解当前代码为什么会添加99999个侦听器?@Bergi老实说,事实并非如此。我知道我对订阅有限制,但这段代码似乎只添加了新的观察者,而已经添加的观察者在工作时不起作用all@YafimDziuko问题是它不会在添加侦听器之后等待。因此,在接下来的迭代中(
ableToWrite
仍然为false),它将继续添加所有侦听器—甚至在第一个事件触发之前添加所有侦听器。当它触发时,它会触发所有等待它的侦听器。你需要另一种流控制方法:递归函数、生成器等。你知道为什么你当前的代码会添加99999个侦听器吗?@Bergi说实话,这不是真的。我知道我对订阅有限制,但这段代码似乎只添加了新的观察者,而已经添加的观察者在工作时不起作用all@YafimDziuko问题是它不会在添加侦听器之后等待。因此,在接下来的迭代中(
ableToWrite
仍然为false),它将继续添加所有侦听器—甚至在第一个事件触发之前添加所有侦听器。当它触发时,它会触发所有等待它的侦听器。
是否会等待新的承诺(fileWriteStream.one.bind(fileWriteStream,'drain'))
工作?不确定这是否是一个好主意,因为这可能会隐式地对
拒绝
做一些事情,但我从未测试过。@PatrickRoberts我想它会像忽略第三个参数一样工作,但我仍然认为这不是一个好主意,因为arrow函数更具可读性。@Bergi第一个解决方案非常好,thx!但你们能解释一件事吗?直到新的承诺无法解决,因为循环将暂停?看起来应该这样,因为文件中的行顺序似乎correct@Bergi测试它,等待新的承诺真的暂停循环,直到它不会得到解决。哇!非常感谢您的帮助将
等待新的承诺(fileWriteStream.one.bind(fileWriteStream,'drain'))
工作吗?不确定这是否是一个好主意,因为这可能会隐式地对
拒绝
做一些事情,但我从未测试过。@PatrickRoberts我想它会像忽略第三个参数一样工作,但我仍然认为这不是一个好主意,因为arrow函数更具可读性。@Bergi第一个解决方案非常好,thx!但你们能解释一件事吗?直到新的承诺无法解决,因为循环将暂停?看起来应该这样,因为文件中的行顺序似乎correct@Bergi测试它,等待新的承诺真的暂停循环,直到它不会得到解决。哇!非常感谢你的帮助
function go(i) {
    if (i >= 1e6) return;
    const ableToWrite = fileWriteStream.write(`.testClass${itr}-${i%2} { background: red } \n`);
    if (ableToWrite)
        go(i+1);
    else
        fileWriteStream.once('drain', () => {
            go(i+1);
        });
}
const fileWriteStream = fs.createWriteStream(path.resolve(filePath));
go(0);