File watcher with Node.js
In this article I am going to explain how to create a file watcher in Node.js that constantly check a source folder content file and moves the content in a destination folder lowering case the name.
It is a great way to understand how listeners and callbacks interact to each other and how to work with asynchronous logic!
Just for fun and excercise I wrote the watcher both in ES5 and ES6.
ES6 version:
const events = require("events"),
util = require("util");
const fs = require("fs"),
watchDir = "./watch",
processedDir = "./done";
/*Let's extend events.EventEmitter in order to be able
to emit and listen for event*/
class Watcher extends events.EventEmitter {
constructor(watchDir, processedDir) {
super();
this.watchDir = watchDir;
this.processedDir = processedDir;
}
/* Cycles through directory and process any file
found emitting a process event for each one*/
watch() {
const watcher = this;
fs.readdir(this.watchDir, function(err, files) {
if (err) throw err;
for (let index in files) {
watcher.emit("process", files[index]);
}
});
}
/* Start the directory monitoring
leveraging Node's fs.watchFile */
start() {
var watcher = this;
fs.watchFile(watchDir, function() {
watcher.watch();
});
}
}
/* Let's instantiate our Watcher object
passing to the constructor our folders path */
let watcher = new Watcher(watchDir, processedDir);
/*Let's use the on method inherited from
event emitter class to listen for process
events and move files from source folder
to destination*/
watcher.on("process", function process(file) {
const watchFile = this.watchDir + "/" + file;
const processedFile = this.processedDir + "/" + file.toLowerCase();
fs.rename(watchFile, processedFile, function(err) {
if (err) throw err;
});
});
/*Start it!!!*/
watcher.start();
You can now create the folders, and run your script with node. Have fun!
And this is the ES5 version:
var events = require("events"),
util = require("util");
var fs = require("fs"),
watchDir = "./watch",
processedDir = "./done";
function Watcher(watchDir, processedDir) {
this.watchDir = watchDir;
this.processedDir = processedDir;
}
util.inherits(Watcher, events.EventEmitter);
Watcher.prototype.watch = function() {
var watcher = this;
fs.readdir(this.watchDir, function(err, files) {
if (err) throw err;
for (var index in files) {
watcher.emit("process", files[index]);
}
});
};
Watcher.prototype.start = function() {
var watcher = this;
fs.watchFile(watchDir, function() {
watcher.watch();
});
};
var watcher = new Watcher(watchDir, processedDir);
watcher.on("process", function process(file) {
var watchFile = this.watchDir + "/" + file;
var processedFile = this.processedDir + "/" + file.toLowerCase();
fs.rename(watchFile, processedFile, function(err) {
if (err) throw err;
});
});
watcher.start();
Seems like only a little bit of work to extend this to a remote folder that is not mounted. (ssh or ftp).
Nice!
Would use
require('path')
for building paths and file namesThanks!