fs.watch fired twice when I change the watched file

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

OUTPUT:

  • some data
  • Done X 1
  • some data
  • Done X 2

It is my usage fault or ..?

The fs.watch api:

  1. is unstable
  2. has known "behaviour" with regards repeated notifications. Specifically, the windows case being a result of windows design, where a single file modification can be multiple calls to the windows API

I make allowance for this by doing the following:

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

If you need to watch your file for changes then you can check out my small library on-file-change. It checks file sha1 hash between fired change events.

first is change and the second is rename

we can make a difference from the listener function

function(event, filename) {

}

The listener callback gets two arguments (event, filename). event is either 'rename' or 'change', and filename is the name of the file which triggered the event.

// rm sourcefile targetfile
fs.watch( sourcefile_dir , function(event, targetfile)){
    console.log( targetfile, 'is', event)
}

as a sourcefile is renamed as targetfile, it's will call three event as fact

null is rename // sourcefile not exist again
targetfile is rename
targetfile is change

notice that , if you want catch all these three evnet, watch the dir of sourcefile

I somtimes get multible registrations of the Watch event causing the Watch event to fire several times. I solved it by keeping a list of watching files and avoid registering the event if the file allready is in the list:

 var watchfiles = {};

function initwatch(fn, callback) {
    if watchlist[fn] {
        watchlist[fn] = true;
        fs.watch(fn).on('change', callback);
    }
}

......

Similar/same problem. I needed to do some stuff with images when they were added to a directory. Here's how I dealt with the double firing:

var fs = require('fs');
var working = false;

fs.watch('directory', function (event, filename) {
  if (filename && event == 'change' && active == false) {
    active = true;

    //do stuff to the new file added

    active = false;
});

It will ignore the second firing until if finishes what it has to do with the new file.