当我更改监视文件时,fs.watch会两次触发

avi*_*abs 28 watch node.js windows-8

 fs.watch( 'example.xml', function ( curr, prev ) {
   // on file change we can read the new xml
   fs.readFile( 'example.xml','utf8', function ( err, data ) {
     if ( err ) throw err;
     console.dir(data);
     console.log('Done');
   });
 });
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

  • 一些数据
  • 完成X 1
  • 一些数据
  • 完成X 2

这是我的使用错误还是..?

Per*_* P. 40

fs.watchAPI:

  1. 不稳定
  2. 已经知道重复通知的"行为".具体来说,windows case是windows设计的结果,其中单个文件修改可以是对windows API的多次调用

  • 我在Windows上测试时遇到了同样的问题.我切换到`fs.watchFile()`而不是`fs.watch()`,两种方法都标记为不稳定,但它解决了我的问题. (10认同)
  • 我在linux环境下用vim编辑目标文件时遇到同样的问题 (3认同)
  • fs.watch 现在很好(在 2019 年),change 事件被触发一次。 (2认同)

小智 17

我通过以下方式考虑到这一点:

var fsTimeout

fs.watch('file.js', function(e) {

    if (!fsTimeout) {
        console.log('file.js %s event', e)
        fsTimeout = setTimeout(function() { fsTimeout=null }, 5000) // give 5 seconds for multiple events
    }
}
Run Code Online (Sandbox Code Playgroud)

  • Underscore.js称之为"debounce" (3认同)

Art*_*n72 13

我建议使用chokidar(https://github.com/paulmillr/chokidar),它比以下更好fs.watch:

评论其README.md:

Node.js fs.watch:

  • 不报告OS X上的文件名.
  • 在OS X上使用Sublime等编辑器时,根本不报告事件.
  • 经常报告两次事件.
  • 发布大多数更改为rename.
  • 很多其他的问题
  • 不提供递归查看文件树的简单方法.

Node.js fs.watchFile:

  • 事件处理几乎一样糟糕.
  • 也不提供任何递归观看.
  • 导致高CPU利用率.


Jan*_*cki 10

如果您需要查看文件以进行更改,那么您可以查看我的小型库文件更改.它检查触发change事件之间的文件sha1哈希.

解释为什么我们有多个被激活的事件:

在某些情况下,您可能会注意到单个创建事件会生成由组件处理的多个Created事件.例如,如果使用FileSystemWatcher组件来监视目录中新文件的创建,然后使用记事本创建文件进行测试,即使只创建了一个文件,也可能会看到生成两个Created事件.这是因为Notepad在写入过程中执行多个文件系统操作.记事本批量写入磁盘,创建文件的内容,然后创建文件属性.其他应用程序可以以相同的方式执行.由于FileSystemWatcher监视操作系统活动,因此将拾取这些应用程序触发的所有事件.

资源


Las*_*tad 6

我的定制解决方案

我个人喜欢使用return来防止在检查某些内容时运行代码块,所以,这是我的方法:

var watching = false;
fs.watch('./file.txt', () => {
    if(watching) return;
    watching = true;

    // do something

    // the timeout is to prevent the script to run twice with short functions
    // the delay can be longer to disable the function for a set time
    setTimeout(() => {
        watching = false;
    }, 100);
};
Run Code Online (Sandbox Code Playgroud)

请随意使用此示例来简化您的代码。它可能并不比使用其他人的模块更好,但它工作得很好!