Javascript nodejs:原子文件替换操作,只触发一次某些观察者
我有两种过程。一个人写一个文件,其他人读它,如果它被改变了 我发现,如果必须重新加载文件,可以通知读取进程 要编写文件,我可以使用 但我不确定这是否是原子替代品。如果文件很大,是否会多次触发Javascript nodejs:原子文件替换操作,只触发一次某些观察者,javascript,node.js,watch,Javascript,Node.js,Watch,我有两种过程。一个人写一个文件,其他人读它,如果它被改变了 我发现,如果必须重新加载文件,可以通知读取进程 要编写文件,我可以使用 但我不确定这是否是原子替代品。如果文件很大,是否会多次触发监视 正确的方法是什么,让它成为原子操作 仅供参考:在目标系统上运行Linux。经过一些测试,我得到以下结果: fs.watch在写入大文件时多次触发change事件。问题是,您看不到写入操作已经完成,这将是最后一个要解决的问题 解决方案是:在同一目录中写入一个临时文件,然后使用link和unlink将旧文件
监视
正确的方法是什么,让它成为原子操作
仅供参考:在目标系统上运行Linux。经过一些测试,我得到以下结果:
fs.watch
在写入大文件时多次触发change
事件。问题是,您看不到写入操作已经完成,这将是最后一个要解决的问题
解决方案是:在同一目录中写入一个临时文件,然后使用link
和unlink
将旧文件替换为新文件
在代码中,它可能如下所示:
var fs = require("fs");
var path = require("path");
var consts = require('constants');
/**
* write given date in temp file and replace the dstpath with that.
*
* @author Tobias Lindig
*
* @param {string} dstpath destination path
* @param {string} data [description]
*
* @throws {Error} If fs operations failed.
*/
function atomicWrite(dstpath, data) {
// build a unique temp path
var dir = path.dirname(dstpath);
var tempName = [
'temp',
process.pid,
(Math.random() * 0x1000000000).toString(36),
new Date().getTime()
].join('-');
var tempPath = path.join(dir, tempName);
var tempOptions = {
encoding: 'utf8',
mode: 420, // aka 0644 in Octal
flags: consts.O_CREAT | consts.O_TRUNC | consts.O_RDWR | consts.O_EXCL
};
//local function to remove temp file
var fn_removeTempFileSync = function() {
try {
fs.unlinkSync(tempPath);
} catch (ex) {
// ignore fail, may be file was not created.
}
};
try {
fs.writeFileSync(tempPath, data, tempOptions);
// remove possible old version of file
// because fs.link can not overwrite existing dstpath.
if (fs.existsSync(dstpath)) {
fs.unlinkSync(dstpath);
}
//copy temp file to destination path
fs.linkSync(tempPath, dstpath);
fn_removeTempFileSync();
} catch (ex) {
fn_removeTempFileSync();
throw ex;
}
}
现在fs.watch
只为文件(“dstpath”)触发一次事件change
这就是理论
但在现实世界中,不幸的是,change
事件并不是在所有情况下都被触发的,它错过了一些时间。因此,我还观看了重命名事件
活动将按以下顺序进行:
重命名
//如果文件被删除
rename
//曾经创建过一个文件
change
//有时会创建文件
为了只读取一次文件,我使用文件的mtime
,如果它不同,则为只读 经过一些测试,我得到了以下结果:
fs.watch
在写入大文件时多次触发change
事件。问题是,您看不到写入操作已经完成,这将是最后一个要解决的问题
解决方案是:在同一目录中写入一个临时文件,然后使用link
和unlink
将旧文件替换为新文件
在代码中,它可能如下所示:
var fs = require("fs");
var path = require("path");
var consts = require('constants');
/**
* write given date in temp file and replace the dstpath with that.
*
* @author Tobias Lindig
*
* @param {string} dstpath destination path
* @param {string} data [description]
*
* @throws {Error} If fs operations failed.
*/
function atomicWrite(dstpath, data) {
// build a unique temp path
var dir = path.dirname(dstpath);
var tempName = [
'temp',
process.pid,
(Math.random() * 0x1000000000).toString(36),
new Date().getTime()
].join('-');
var tempPath = path.join(dir, tempName);
var tempOptions = {
encoding: 'utf8',
mode: 420, // aka 0644 in Octal
flags: consts.O_CREAT | consts.O_TRUNC | consts.O_RDWR | consts.O_EXCL
};
//local function to remove temp file
var fn_removeTempFileSync = function() {
try {
fs.unlinkSync(tempPath);
} catch (ex) {
// ignore fail, may be file was not created.
}
};
try {
fs.writeFileSync(tempPath, data, tempOptions);
// remove possible old version of file
// because fs.link can not overwrite existing dstpath.
if (fs.existsSync(dstpath)) {
fs.unlinkSync(dstpath);
}
//copy temp file to destination path
fs.linkSync(tempPath, dstpath);
fn_removeTempFileSync();
} catch (ex) {
fn_removeTempFileSync();
throw ex;
}
}
现在fs.watch
只为文件(“dstpath”)触发一次事件change
这就是理论
但在现实世界中,不幸的是,change
事件并不是在所有情况下都被触发的,它错过了一些时间。因此,我还观看了重命名事件
活动将按以下顺序进行:
重命名
//如果文件被删除
rename
//曾经创建过一个文件
change
//有时会创建文件
为了只读取一次文件,我使用文件的mtime
,如果它不同,则为只读