Node.js fs

Originally posted here on Sept. 12, 2018.

fs.watch()

We’re going to take a brief look at a function in the Node Filesystem module.

What exactly is Node fs? It’s a Node module that allows you to directly manipulate files on your computer through a browser. Let’s say you use a site to draw something, Instead of downloading the picture for example, you can just directly save it onto you computer.

It’s a pretty interesting tool that cuts out a lot of bloat from passing requests to a server to do filesystem handling.

There’s an interesting function called fs.watch and according to the docs, it should be used whenever possible to replace fs.watchFile and fs.unwatchFile. However, we will look at those two as well.

fs.watch format:

fs.watch(filename[, options][, listener])

Where [options] can be either: 
 persistent => indicates whether the process should continue to run as long as files are being watched
 recursive => indicates wither all subdirectories should be watched or only the current directory (Only supported on macOS and Windows)
 encoding => specifies the character encoding to be used for the filename passed to the listener,

And where [listener] gets back either
 eventType => which can be rename or change or
 filename => the name of the file that triggered the event.

This function returns an fs.FSWatcher object, all of which are EventEmitters that will emit a change event whenever the specified file is modified. Some events that can be handled include change, close (when watched stops watching and the object becomes unusable in the event handler), error (when an error occurs during watching a file, unusable object), watcher.close (which is not an event but stops watching for changes on the FSWatcher, also unusable object).

fs.watchFile format

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

Even though the docs prefer the developer to use watch, this function automatically returns each time the file is accessed.

Its options are persistent (same as fs.watch), and interval, which can indicated how often the target file should be polled in milliseconds, which again is useful for version control.

The listener options receive two arguments, current and previous (in the form of an fs.Stats object) and that object comes with a lot of interesting information such as birth time, user ids, etc. If you compare the current and previous objects mtimes variables you can not only get information on when the file was accessed but also when it was modified.

fs.unwatchFile format

fs.unwatchFile(filename[,listener])

This function merely stops watching changes on filename. Which is similar to watch’s watcher.close.

You can specify a listener, so only that listener is removed, otherwise all of them are removed, effectively stopping watching of the file which is also interesting if you want to only have specific functions ignore the file. It also allows a listener previous attached using the watchFile command.

What’s interesting about these functions is that you can have files be monitored and run processes depending on the changes in the file. You could essentially program a Git-like version controller through the browser that warns about changes and even goes a step further to say what caused the file to change.

The only caveat is that if the underlying functionality of the OS does not provide a way to be notified of filesystem changes, this will be unable to function. For example network file systems like NFS or host file systems using virtualization like Vagrant or Docker, although it seems that even in this cases you can utilize fs.watchFile() but it will use stat polling * which is considered not as efficient.

* The best explanation for stat polling I’ve found is taken from wikipedia:
 “Polling is the process where the computer or controlling device waits for an external device to check for its readiness or state, often with low-level hardware. For example, when a printer is connected via a parallel port, the computer waits until the printer has received the next character.”