将频繁更改的 JavaScript 对象写入 NodeJS 文件的最有效方法是什么?
What is the most efficient way to keep writing a frequently changing JavaScript object to a file in NodeJS?
我有一个具有许多不同属性的 JavaScript 对象,它可能看起来像这样:
var myObj = {
prop1: "val1",
prop2: [...],
...
}
此对象中的值不断更新(每秒几次),可能有数千个。可以添加新值,可以更改或删除现有值。
我想要一个始终包含此对象更新版本的文件。这样做的简单方法就是在每次更改后将整个对象重新写入文件,如下所示:
fs.writeFileSync("file.json", JSON.stringify(myObj));
对于需要非常频繁写入的大对象,这似乎不是很有效。有更好的方法吗?
你应该使用数据库。像 sqlite3 这样简单的东西将是一个不错的选择。有一个只有两列 'Key' 'Value' 的 table 并将其用作键值存储。您将获得诸如交易和比文件更好的性能等优势,并简化您的访问。
维护包含快速变化对象当前状态的文件(在文件系统上)非常困难。具体来说,设置一些其他程序可以随时 读取 文件是困难的部分。为什么?文件可能随时处于写入过程中,因此 reader 可能会得到不一致的结果。
这里概述了执行此操作的一个好方法。
1) 写入文件的频率低于每次状态变化时的频率。每当状态改变时调用 updateFile (myObj)
。它设置一个计时器,比方说,500 毫秒,然后在计时器到期时将最新状态写入文件。像这样:未调试:
let latestObj
let updateFileTimer = 0
function updateFile (myObj) {
latestObj = myObj
if (updateFileTimer === 0) {
updateFileTimer = setTimeout (
function () {
/* write latestObj to the file */
updateFileTimer = 0
}, 500)
}
}
这会将对象的最新状态写入文件,但不会超过每 500 毫秒一次。
在那个超时函数里面,写出一个临时文件。写入时删除现有文件并将临时文件重命名为具有现有文件的名称。异步执行所有这些操作,这样程序的其余部分就不必等待文件系统工作。您的超时函数将如下所示
updateFileTimer = setTimeout (
function () {
/* write latestObj to the file */
fs.writeFile("file.json.tmp",
JSON.stringify(myObj),
function (err) {
if (err) throw err;
fs.unlink ( "file.json",
function (err) {
if (!err)
fs.renameSync( "file.json.tmp", "file.json")
} )
} )
updateFileTimer = 0
}, 500)
还有一件事要担心。在 unlink
和 renameSync
操作之间有一小段时间,文件系统中不存在 "file.json" 文件。因此,如果找不到文件,您编写的任何读取 "file.json" 的程序都需要重试。
如果您使用 Linux、MacOs、FreeBSD 或其他 UNIX-derived 操作系统来运行此代码,它将运行良好。这些操作系统的文件系统允许一个程序在另一个程序读取文件时取消链接文件。如果您 运行 它在像 Windows 这样的 DOS-derived 操作系统上,当另一个程序正在读取文件时,取消链接操作将失败。
我有一个具有许多不同属性的 JavaScript 对象,它可能看起来像这样:
var myObj = {
prop1: "val1",
prop2: [...],
...
}
此对象中的值不断更新(每秒几次),可能有数千个。可以添加新值,可以更改或删除现有值。
我想要一个始终包含此对象更新版本的文件。这样做的简单方法就是在每次更改后将整个对象重新写入文件,如下所示:
fs.writeFileSync("file.json", JSON.stringify(myObj));
对于需要非常频繁写入的大对象,这似乎不是很有效。有更好的方法吗?
你应该使用数据库。像 sqlite3 这样简单的东西将是一个不错的选择。有一个只有两列 'Key' 'Value' 的 table 并将其用作键值存储。您将获得诸如交易和比文件更好的性能等优势,并简化您的访问。
维护包含快速变化对象当前状态的文件(在文件系统上)非常困难。具体来说,设置一些其他程序可以随时 读取 文件是困难的部分。为什么?文件可能随时处于写入过程中,因此 reader 可能会得到不一致的结果。
这里概述了执行此操作的一个好方法。
1) 写入文件的频率低于每次状态变化时的频率。每当状态改变时调用 updateFile (myObj)
。它设置一个计时器,比方说,500 毫秒,然后在计时器到期时将最新状态写入文件。像这样:未调试:
let latestObj
let updateFileTimer = 0
function updateFile (myObj) {
latestObj = myObj
if (updateFileTimer === 0) {
updateFileTimer = setTimeout (
function () {
/* write latestObj to the file */
updateFileTimer = 0
}, 500)
}
}
这会将对象的最新状态写入文件,但不会超过每 500 毫秒一次。
在那个超时函数里面,写出一个临时文件。写入时删除现有文件并将临时文件重命名为具有现有文件的名称。异步执行所有这些操作,这样程序的其余部分就不必等待文件系统工作。您的超时函数将如下所示
updateFileTimer = setTimeout (
function () {
/* write latestObj to the file */
fs.writeFile("file.json.tmp",
JSON.stringify(myObj),
function (err) {
if (err) throw err;
fs.unlink ( "file.json",
function (err) {
if (!err)
fs.renameSync( "file.json.tmp", "file.json")
} )
} )
updateFileTimer = 0
}, 500)
还有一件事要担心。在 unlink
和 renameSync
操作之间有一小段时间,文件系统中不存在 "file.json" 文件。因此,如果找不到文件,您编写的任何读取 "file.json" 的程序都需要重试。
如果您使用 Linux、MacOs、FreeBSD 或其他 UNIX-derived 操作系统来运行此代码,它将运行良好。这些操作系统的文件系统允许一个程序在另一个程序读取文件时取消链接文件。如果您 运行 它在像 Windows 这样的 DOS-derived 操作系统上,当另一个程序正在读取文件时,取消链接操作将失败。