node.js - `fs.appendFile()` 的原子性保证是什么?

标签 node.js

fs.appendFile() 的文档对于原子性保证含糊不清。

我特别想知道,如果在同一个文件上对数据进行两次或多次调用,而不等待其间的回调,是否可以交错或删除数据(例如,由于写入重叠区域)。例如,采用以下代码:

fs.writeFileSync('blort.bin', '');
for (let i = 0; i < 10; i++) {
  const data = Buffer.alloc(65536, i);
  fs.appendFile('blort.bin', data, () => {});
}

假设没有文件系统错误并且没有其他进程写入相关文件,那么在完成所有追加操作后,Node 会做出以下保证吗?:

  • 文件大小正好为 640k。
  • 该文件由 10 个 64k 数据 block 组成,每个数据 block 统一包含一个字节值。

我也很好奇是否有任何序列化保证(尽管我认为没有)。也就是说,追加是否保证按顺序执行?

更新:添加了说明,表明这是作用于该文件的唯一代码。

最佳答案

据我所知,您的追加将按顺序进行,除非另一个进程正在写入目标文件,否则不会覆盖现有数据。

Node 是单线程的(从正在运行的应用程序的角度来看),并在内部对文件写入进行排队,因此如果将 1 23 写入文件,该文件将包含 123

Node 确实会启动新线程来处理 IO,但这是运行时的一项功能,对开发人员是隐藏的。

更新

在第一次阅读时,我错过了您的要求,即您的附加发生在回调为空或不起作用的多个调用中。

这极大地改变了事情。

如果您使用异步调用,例如fs.appendFile(),则必须提供一个必须检查错误的回调。如果您在不等待回调结束的情况下堆叠异步调用,则无法保证您的写入会按顺序发生或不会覆盖以前的数据。

底线:如果没有始终检查错误的适当回调,请勿使用异步函数。

否则就会破坏 Node 事件驱动模型的整个理念。

我通常解释这一点的方式是考虑到,在异步调用中,由于包括 cpu 和 IO 负载在内的众多因素,您无法预测何时触发回调

如果您无法知道回调何时被触发,则无法预测多个调用将按顺序运行。

更新2

需要明确的是,您无法在不提供回调的情况下调用异步函数并保证任何预期行为。

从事件的角度思考:

fs.appendFile() 将事件处理程序添加到 IO 线程,并将包含其参数的事件发送到 IO 线程。

操作完成后,将触发此事件处理程序,该事件处理程序要么是您的回调,要么将触发您的回调。

如果不等待操作完成,则无法保证操作已成功或已完成您期望的操作。

关于node.js - `fs.appendFile()` 的原子性保证是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44464284/

相关文章:

node.js - 如何创建 Mongoose 方法将图像写入 cloudinary

node.js - npm 中的身份验证 token 是什么?

javascript - 对话流 : Getting in an array all document IDs of a firestore collection (javascript node)

node.js - 正则表达式将 Markdown 中的文本 URL 转换为链接

javascript - node.js:从函数返回未按预期运行

node.js - Nexmo 不在 node.js 中发送短信

javascript - 如何检测客户端与 node.js 服务器的断开连接

node.js - Clob 在 Express 应用程序中无法正确打印

mysql - 启动服务器后,带有sequelize的Nodejs无法在mysql工作台中创建表

javascript - sailsjs 在 Controller 工作时更新 View