【问题标题】:Why fs.watchFile called twice in Node?为什么 fs.watchFile 在 Node 中调用了两次?
【发布时间】:2012-05-15 03:49:38
【问题描述】:

Ubuntu 12.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.log 'msg: ', msg
  print "!! #{coffee_eval}\n"

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

每次我保存观看的文件时,主函数都会调用 twitce 而不是一次。
我的编辑器是 Sumlime Text 2。

输出的话可以看:

【问题讨论】:

  • 我在 Windows 上使用 fs.watch 时遇到了同样的问题。有趣的是,使用 fs.watchFile(他们在文档中建议反对)效果很好。

标签: node.js


【解决方案1】:

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

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

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

【讨论】:

【解决方案2】:

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

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

【讨论】:

    【解决方案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
    });
    

    我们在继续之前检查最后修改时间是否不同。

    【讨论】:

    • imo 这是避免重复触发的最可靠方法
    【解决方案4】:

    另一个比 fs.watchfs.watchFile 更好的 npm 模块建议:

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

    【讨论】:

      【解决方案5】:

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

      this question 对此问题进行了更多讨论。我还在那里为我的解决方案发布了一些示例代码。

      【讨论】:

        【解决方案6】:

        如果您使用下划线或 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();
        

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

            我建议尝试 node-inotify-plusplus (https://github.com/coolaj86/node-inotify-plusplus),它对我来说比 fs.watchFile 或 fs.watch 效果更好。

            【讨论】:

              【解决方案9】:

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

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

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

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

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

              【讨论】:

              • 截至 2017 年 1 月,fs.watchfs.watchFile 或多或少是稳定的(文档没有明确提及它们的稳定性问题),但确实有它们的 caveats 和细微差别跨平台
              • fwiw 这些问题在 2019 年仍然存在
              猜你喜欢
              • 2012-12-12
              • 1970-01-01
              • 2013-11-20
              • 2019-10-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多