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

问题描述 投票:2回答:10

Ubuntu 12.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"

要点上的整个代码:https://gist.github.com/2621576

每次我保存一个被监视的文件时,主函数被调用两次而不是一次。 我的编辑是Sublime Text 2。

输出字可以看出:

node.js
10个回答
4
投票

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

fs.watchFile(filename,[options],listener)#

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

你可以尝试fs.watch,但不幸的是它可能会遇到同样的问题。当我试图创建一个类似的fs.watch时,我在Windows上与monitor script有同样的问题。

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


0
投票

现在已经解决了问题(至少)与fs.watch。我没有尝试fs.watchFile,因为它不是NodeJS文档推荐的。

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

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


3
投票

问题仍然存在,这是我找到的方式。

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
});

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


1
投票

我建议尝试node-inotify-plusplus(https://github.com/coolaj86/node-inotify-plusplus),它比fs.watchFile或fs.watch更适合我。


1
投票

如果你使用下划线或lodash,你可以考虑使用油门并丢弃后缘上的调用。一个基本的例子是

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();

0
投票

为了解决这个问题,我跟踪以前的“文件修改”时间戳,如果值相同,则不运行我的正常回调代码。

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
    });
});

0
投票

我通过每次收到更新时将'ignore'标志从false翻转为true来解决这个问题,从而忽略每一个第二个事件。但我还发现,有时,对文件的更改只会导致一次更新。我不确定是什么导致了这种情况,但是当更新非常频繁,并且当这些更新被追加时(>>),它似乎发生了。我没有观察到任何触发两个以上事件的单个更改的实例。

this question中有关于这个问题的更多讨论。我还为我的解决方案发布了一些示例代码。


0
投票

另一个建议是npm模块比fs.watchfs.watchFile好得多:

https://github.com/paulmillr/chokidar/


0
投票

debouncing相似:

let fsWait = false;
fs.watch("file.txt", (event, filename) => {
  if(fsWait)return;
  fsWait = setTimeout(() => fsWait = false, 1000);
  /* own code here */
});

0
投票

它与原始问题没有直接关系,但你知道这句话是什么意思吗? (来自fs.watch documentation)。

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

© www.soinside.com 2019 - 2024. All rights reserved.