fs.watch fired twice when I change the watched file

后端 未结 12 1307
星月不相逢
星月不相逢 2020-12-09 01:30
 fs.watch( \'example.xml\', function ( curr, prev ) {
   // on file change we can read the new xml
   fs.readFile( \'example.xml\',\'utf8\', function ( err, data ) {         


        
相关标签:
12条回答
  • 2020-12-09 02:15

    I'm dealing with this issue for the first time, so all of the answers so far are probably better than my solution, however none of them were 100% suitable for my case so I came up with something slightly different – I used a XOR operation to flip an integer between 0 and 1, effectively keeping track of and ignoring every second event on the file:

    var targetFile = "./watchThis.txt"; 
    var flippyBit = 0; 
    
    fs.watch(targetFile, {persistent: true}, function(event, filename) {
    
          if (event == 'change'){
            if (!flippyBit) {
              var data = fs.readFile(targetFile, "utf8", function(error, data) {
                gotUpdate(data);
              })
            } else {
              console.log("Doing nothing thanks to flippybit.");              
            }
            flipBit(); // call flipBit() function
          }
        });
    
    // Whatever we want to do when we see a change
    function gotUpdate(data) {
        console.log("Got some fresh data:");
        console.log(data);
        }
    
    
    // Toggling this gives us the "every second update" functionality
    
    function flipBit() {
        flippyBit = flippyBit ^ 1;
    }
    

    I didn't want to use a time-related function (like jwymanm's answer) because the file I'm watching could hypothetically get legitimate updates very frequently. And I didn't want to use a list of watched files like Erik P suggests, because I'm only watching one file. Jan Święcki's solution seemed like overkill, as I'm working on extremely short and simple files in a low-power environment. Lastly, Bernado's answer made me a little nervous – it would only ignore the second update if it arrived before I'd finished processing the first, and I can't handle that kind of uncertainty. If anyone were to find themselves in this very specific scenario, there might be some merit to the approach I used? If there's anything massively wrong with it please do let me know/edit this answer, but so far it seems to work well?

    NOTE: Obviously this strongly assumes that you'll get exactly 2 events per real change. I carefully tested this assumption, obviously, and learned its limitations. So far I've confirmed that:

    • Modifying a file in Atom editor and saving triggers 2 updates
    • touch triggers 2 updates
    • Output redirection via > (overwriting file contents) triggers 2 updates
    • Appending via >> sometimes triggers 1 update!*

    I can think of perfectly good reasons for the differing behaviours but we don't need to know why something is happening to plan for it – I just wanted to stress that you'll want to check for yourself in your own environment and in the context of your own use cases (duh) and not trust a self-confessed idiot on the internet. That being said, with precautions taken I haven't had any weirdness so far.

    * Full disclosure, I don't actually know why this is happening, but we're already dealing with unpredictable behaviour with the watch() function so what's a little more uncertainty? For anyone following along at home, more rapid appends to a file seem to cause it to stop double-updating but honestly, I don't really know, and I'm comfortable with the behaviour of this solution in the actual case it'll be used, which is a one-line file that will be updated (contents replaced) like twice per second at the fastest.

    0 讨论(0)
  • 2020-12-09 02:15

    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

    0 讨论(0)
  • 2020-12-09 02:17

    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.

    Explanation of why we have multiple fired events:

    You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use a FileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the operating system activities, all events that these applications fire will be picked up.

    Source

    0 讨论(0)
  • 2020-12-09 02:19

    Like others answers says... This got a lot of troubles, but i can deal with this in this way:

    var folder = "/folder/path/";
    
    var active = true; // flag control
    
    fs.watch(folder, function (event, filename) {
        if(event === 'rename' && active) { //you can remove this "check" event
            active = false;
    
            // ... its just an example
            for (var i = 0; i < 100; i++) {
                console.log(i);
            }
    
            // ... other stuffs and delete the file
            if(!active){
                try {
                    fs.unlinkSync(folder + filename);
                } catch(err) {
                    console.log(err);
                }
                active = true
            }
        }
    });
    

    Hope can i help you...

    0 讨论(0)
  • 2020-12-09 02:24

    I was downloading file with puppeteer and once a file saved, I was sending automatic emails. Due to problem above, I noticed, I was sending 2 emails. I solved by stopping my application using process.exit() and auto-start with pm2. Using flags in code didn't saved me.

    If anyone has this problem in future, one can use this solution as well. Exit from program and restart with monitor tools automatically.

    0 讨论(0)
  • 2020-12-09 02:33

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题