Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript nodejs:原子文件替换操作,只触发一次某些观察者_Javascript_Node.js_Watch - Fatal编程技术网

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
,如果它不同,则为只读