Can多个fs.写入追加到同一文件保证执行顺序

Can Multiple fs.write to append to the same file guarantee the order of execution?

本文关键字:文件 顺序 执行 fs 多个 追加 Can      更新时间:2023-09-26

假设我们有这样一个程序:

// imagine the string1 to string1000 are very long strings, which will take a while to be written to file system
var arr = ["string1",...,"string1000"]; 
for (let i = 1; i < 1000; i++) {
  fs.write("./same/path/file.txt", arr[i], {flag: "a"}});
}

我的问题是,will string1 to string1000 be gurantted to append to the same file in order?

因为fs。write是异步函数,我不确定每次调用fs.write()是如何真正执行的。我假设对每个字符串的函数调用应该放在another thread中的某个地方(如callstack ?),一旦前一个调用完成,下一个调用可以执行。

我不确定我的理解是否准确。

编辑1

在评论和回答中,我看到fs.write在不等待callback的情况下多次写入同一文件是不安全的。但是写流呢?

如果我使用下面的代码,它能保证写入的顺序吗?

// imagine the string1 to string1000 are very long strings, which will take a while to be written to file system
var arr = ["string1",...,"string1000"]; 
var fileStream = fs.createWriteFileStream("./same/path/file.txt",  { "flags": "a+" });
for (let i = 1; i < 1000; i++) {
  fileStream.write(arr[i]);
}
fileStream.on("error", () => {// do something});
fileStream.on("finish", () => {// do something});
fileStream.end();

任何意见或更正将是有帮助的!谢谢!

医生说

注意,在同一个文件上多次使用fs.write而不等待回调是不安全的。对于这个场景,f。强烈建议使用createWriteStream

使用流是有效的,因为流本质上保证写入它们的字符串的顺序与从它们读取的顺序相同。

var stream = fs.createWriteStream("./same/path/file.txt");
stream.on('error', console.error);
arr.forEach((str) => { 
  stream.write(str + ''n'); 
});
stream.end();

另一种仍然使用fs.write的方法是使用promise来维持顺序逻辑。

function writeToFilePromise(str) {
  return new Promise((resolve, reject) => {
    fs.write("./same/path/file.txt", str, {flag: "a"}}, (err) => {
      if (err) return reject(err);
      resolve();
    });
  });
}
// for every string, 
// write it to the file, 
// then write the next one once that one is finished and so on
arr.reduce((chain, str) => {
  return chain
   .then(() => writeToFilePromise(str));
}, Promise.resolve());

您可以使用节点读/写锁定同步对文件的访问,请参阅以下示例,您可以阅读文档

var ReadWriteLock = require('rwlock');
var lock = new ReadWriteLock();
lock.writeLock(function (release) {
  fs.appendFile(fileName, addToFile, function(err, data) {
    if(err) 
      console.log("write error"); //logging error message
    else    
      console.log("write ok");
    release(); // unlock
   });    
});

我遇到了同样的问题,并为我的项目编写了一个NPM包来解决它。它的工作方式是将数据缓冲在数组中,并等待事件循环结束,在对fs.appendFile的单个调用中连接和写入数据:

const SeqAppend = require('seqappend');
const writeLog = SeqAppend('log1.txt');
writeLog('Several...');
writeLog('...logged...');
writeLog('.......events');

你可以使用json-stream包来实现它