Node.js 为什么fs.watchFile在节点中调用了两次?

Node.js 为什么fs.watchFile在节点中调用了两次?,node.js,Node.js,ubuntu12.04Node v0.6.14CoffeeScript 1.3.1 fs.watchFile coffee_eval, (e) -> console.log e result = spawn 'coffee', ['-bc', coffee_eval] msg = '' result.stderr.on 'data', (str) -> msg+= str result.stderr.on 'end', -> console.

ubuntu12.04
Node v0.6.14
CoffeeScript 1.3.1

fs.watchFile coffee_eval, (e) ->
  console.log e
  result = spawn 'coffee', ['-bc', coffee_eval]
  msg = ''
  result.stderr.on 'data', (str) ->
    msg+= str
  result.stderr.on 'end', ->
    console.log 'msg: ', msg
  print "!! #{coffee_eval}\n"
关于要点的完整代码:

每次我保存一个被监视的文件时,主函数被称为twitce,而不是一次。
我的编辑是Sumline Text 2

输出字可参见:

fs.watchFile不稳定。从节点文档:

fs.watchFile(文件名,[options],侦听器)#

稳定性:2-不稳定。如果可用,请改用fs.watch

您可以尝试
fs.watch
,但不幸的是,它可能会遇到同样的问题。在windows上尝试创建类似的应用程序时,我遇到了与fs.watch相同的问题


解决方法是记录修改发生的时间,如果在几毫秒内触发,则忽略第二次更改。有点难看,但它确实有效。

我建议尝试node inotify plusplus(),它比fs.watchFile或fs.watch更适合我。

为了解决这个问题,我会跟踪以前的“file modified”时间戳,如果值相同,就不运行正常的回调代码

var filename = "/path/to/file";
var previousMTime = new Date(0);
var watcher = fs.watch(filename, {
    persistent: false
}, function(){
    fs.stat(filename, function(err, stats){
        if(stats.mtime.valueOf() === previousMTime.valueOf()){
            console.log("File Update Callback Stopped (same revision time)");
            return;
        }
        previousMTime = stats.mtime;

        // do your interesting stuff down here
    });
});

如果你使用下划线或LADASH,你可以考虑使用节流阀并丢弃后缘上的呼叫。一个基本的例子是

var fs = require('fs');
var _ = require("lodash");

function FileWatcher (fileName)
{
    this.file = fileName;
    this.onChange = _.throttle(this.trigger, 100, {leading: false});
}
FileWatcher.prototype.observe = function ()
{
    fs.watch(this.file, this.onChange);
}
FileWatcher.prototype.trigger = function ()
{
    console.log("file changed :)");
}

var fileToWatch = __dirname + "/package.json";
new FileWatcher(fileToWatch).observe();

我解决了这个问题,每次收到更新时都将“忽略”标志从false翻转为true,从而忽略每一秒的事件但是我还发现,有时候,对文件的更改只会导致一次更新。我不确定是什么原因导致了这种情况,但它似乎发生在更新非常频繁的时候,以及那些更新是附加的时候(
>
)。我没有观察到任何单一变化触发两个以上事件的情况


关于这个问题的讨论更多。我还在那里发布了我的解决方案的一些示例代码。

关于npm模块的另一个建议,它比
fs.watch
fs.watchFile
好得多:


问题仍然存在,以下是我找到的方法

var actionDone = {}    
fs.watch('.', function(x,filename) {
        var path = './'+filename;
        var stats = fs.statSync(path);
        let seconds = +stats.mtime;
        if(actionDone[filename] == seconds) return;
        actionDone[filename] = seconds
       //write your code here
});

我们检查上次修改的时间是否不同,然后继续。

这与原始问题没有直接关系,但你知道这句话的意思吗?(从
fs.watch

还要注意,侦听器回调附加到fs.FSWatcher触发的“change”事件,但它与eventType的“change”值不同


该问题已通过
fs(至少)修复。请立即观看
。我没有尝试
fs.watchFile
,因为NodeJS文档不推荐它

  • 每次修改文件时都会发生一个
    change
    事件
  • 2
    重命名
    更改文件名时发生的事件,一个用于当前名称,一个用于新名称
  • 新创建的文件(从其他位置复制)或已删除的文件的一个
    重命名
    事件

我的环境:macOS 10.12.6和NodeJS v11.10.1

截至2017年1月,
fs.watch
fs.watchFile
或多或少都比较稳定(文档没有明确提到它们的稳定性问题),但不同平台之间确实存在细微的差异。这些问题在2019年仍然存在。我在Windows上使用fs.watch时也遇到了同样的问题。有趣的是,使用fs.watchFile(他们在文档中建议不要使用)效果很好。但是,当您实际更改文件内容时,仍会触发两个事件:文件在打开时首先被截断,然后写入数据。请看这里:imo这是避免重复触发器的最可靠的方法