1

我正在使用 Node 的 fs.WriteStream 将数据写入文件。我正在遍历一个对象数组并使用write()函数写入每个对象。

问题是我想知道一旦这个循环结束并且所有的write()调用都完成了,但我不能让它工作。

我尝试了一些解决方案,例如不使用流,但这会产生其他问题。我上次尝试的解决方案是检查循环是否是最后一项,如果是,则关闭、结束或销毁流。

这些都不起作用。该事件是在文件实际写入之前发出的。

下面是我的代码,我很感激我能得到的任何帮助。非常感谢。

    async function writeFile(path, data) {

    try {

        const writeStream = fs.createWriteStream(path, {
            flags: "w"
        })

        data.forEach((file, index) => {
            writeStream.write(`${file.name}\n`, (err) => {
                if(err) throw err
                if(index === (data.length - 1)) writeStream.end(); //I attempted close() and destroy() too, none worked
            })
        })

        writeStream.on("finish", () => {
            console.log("All files were written.") //Currently being emmited before all is written.
        })

    } catch (err) {

        throw (err)
    }
}
4

2 回答 2

2

由于您的文件数据已经在内存中,因此看起来并没有那么大,因此我只需将其转换到内存中并在一次调用中将其写出fs.writeFile()or fs.promises.writeFile()

function writeFile(path, data) {
    let fileData = data.map(file => file.name + "\n").join("");
    return fs.promises.writeFile(path, fileData);
}

如果您真的想使用流,那么您必须非常小心地注意.write()在写入缓冲区已满的情况下返回的内容,以便您可以等待排水事件。

const fs = require('fs');

function writeFile(path, data, completionCallback) {
    let index = 0;
    const writeStream = fs.createWriteStream(path, { flags: "w" });

    writeStream.on('error', function(err) {
        // stream will be automatically closed here
        completionCallback(err);
    });

    // write one piece of data and call callback
    // when ready to write the next piece of data
    function writeData(data, cb) {
        if (!writeStream.write(data)) {
            // when .write() returns false, you have to wait for the drain
            // event before doing any more writing
            stream.once('drain', cb);
        } else {
            // so we always call the callback asynchronously and have no
            // stack buildup
            process.nextTick(cb);
        }
    }

    function run() {
        if (index < data.length) {
            let line = data[index++].name + "\n";
            writeData(line, run);
        } else {
            // all done with no errors
            writeStream.end(completionCallback);
        }
    }

    run();
}
于 2020-11-19T08:59:04.920 回答
0

你能试试这个方法吗

const util = require("util");

async function writeFile(path, data) {
    try {
        const writeStream = fs.createWriteStream(path, {
            flags: "w"
        });

        const promisify = util.promisify(writeStream.write);

        for (const file of data) {
            await promisify(`${file.name}\n`);
        }
        
        writeStream.end();
        writeStream.on("finish", () => {
            console.log("All files were written.");
        });

    } catch (error) {
        console.log('error',error);
        throw (error)'
    }
}
于 2020-11-19T04:00:04.227 回答