Systems Rebooter
Systems Rebooter

Reputation: 1399

How to fire once each time on changing directory content with fs.watch?

Is there a way to fire only once on changing directory content with Node.js fs.watch? By changing directory content I mean adding/deleting bunch of files from it ?

In other words I expect fs.watch to fire on the first event of the first file and ignore any other events for particular changing dir content cycle.

I was able to do this only with fs.watchFile But node guys recommend to use fs.watch if possible.

Note: fs.watch() is more efficient than fs.watchFile and fs.unwatchFile. fs.watch should be used instead of fs.watchFile and fs.unwatchFile when possible.

https://nodejs.org/docs/latest/api/fs.html#fs_fs_watchfile_filename_options_listener

Upvotes: 2

Views: 1799

Answers (1)

Systems Rebooter
Systems Rebooter

Reputation: 1399

Yury Tarabanko patricianly answered this question earlier, but shortly after deleted his answer:

You simply stop watching on the first call

const watcher = fs.watch(somePath, (ev, file) => {
  watcher.close()

  // logic goes here
  console.log(`${ev} ${file}`)
})

With resurrecting watcher after closing it, we will have 1 shot recurrent behavior as asked in the question:

const fs = require('fs')
let dir = './watch1'

function watchOnce()
{
  const watcher = fs.watch(dir, (evt, file) => {
    watcher.close()

    // logic goes here
    console.log(Date(), evt, file)

   // resurrecting watcher after 1 sec
    setTimeout(watchOnce, 1000)
  })
}

watchOnce()

Testing

Creating and deleting 10,000 files 5 times in a raw with 1 seconds delay in between:

$ for i in {1..5}; do touch {1..10000}; sleep 1; rm {1..10000}; sleep 1; done

Verifying that watcher fired exactly 10 times (5 for creating 10,000 files and 5 for deleting 10,000 files):

$ node watchers.js
Wed Jun 07 2017 12:01:44 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:46 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:47 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:49 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:50 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:52 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:53 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:55 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:56 GMT+0300 (EEST) rename 1
Wed Jun 07 2017 12:01:58 GMT+0300 (EEST) rename 1

I will not marking my answer as accepted, since credits mostly goes to Yury for his watcher.close() idea. And maybe someone else will write more neat solution, since I am not big fun using delay in the function.

Upvotes: 4

Related Questions