In the previous post, we’ve known how to watch folder for changes. This tutorial comes with another approach, we won’t listen to a folder with adding file event, read & delete the file. We’re gonna watch file for its changes in Node.js, for example: read the latest line at the time it is added to the file.
Related post: How to watch folder for changes in Node.js
Overview
Watch file for changes in Node.js
We’re gonna create a service working independently of the main project (that updates the log file).
The main project Performance will randomly add a line to the end of info.log
file in logs folder.
So what we will do is watching the info.log
file: If any line is added to info.log
, read & show it.
This is the structure for our example:
Way to watch file for changes
How do we build a service to work for this process?
In previous post, we’ve known that we can use fs.watch
, fs.watchFile
from Node.js fs
module to watch changes of a file, its disadvantages and a new solution: using chokidar module.
We continue to use chokidar module to create a watcher in this tutorial.
Again, I want to show you the overview of chokidar API:
const chokidar = require('chokidar');
// Initialize watcher.
const watcher = chokidar.watch('path/to/folder', { persistent: true });
// Add event listeners.
watcher
.on('add', path => log(`File ${path} has been added`))
.on('change', path => log(`File ${path} has been changed`))
.on('unlink', path => log(`File ${path} has been removed`));
// More possible events.
watcher
.on('addDir', path => log(`Directory ${path} has been added`))
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
.on('error', error => log(`Watcher error: ${error}`))
.on('ready', () => log('Initial scan complete. Ready for changes'))
Next, we use read-last-lines
module for reading the last line of a file:
const readLastLines = require('read-last-lines');
readLastLines.read('path/to/file', 42) // read last 42 lines
.then((lines) => console.log(lines));
Practice
Setup Node.js modules
We need to install 2 packages: chokidar and read-last-lines.
So run the command:
npm install chokidar read-last-lines
Create Service for watching folder
Under services folder, create obserser.js file:
const chokidar = require('chokidar');
const EventEmitter = require('events').EventEmitter;
const readLastLines = require('read-last-lines');
class Observer extends EventEmitter {
constructor() {
super();
}
watchFile(targetFile) {
try {
console.log(
`[${new Date().toLocaleString()}] Watching for file changes on: ${targetFile}`
);
var watcher = chokidar.watch(targetFile, { persistent: true });
watcher.on('change', async filePath => {
console.log(
`[${new Date().toLocaleString()}] ${filePath} has been updated.`
);
// Get update content of file, in this case is one line
var updateContent = await readLastLines.read(filePath, 1);
// emit an event when the file has been updated
this.emit('file-updated', { message: updateContent });
});
} catch (error) {
console.log(error);
}
}
}
module.exports = Observer;
Everything is simple:
– import necessary module: chokidar
, events
, read-last-lines
.
– define Observer
class that extends EventEmitter
which can emit event (emit()
method) and listen to event (on()
method).
– create watcher
variable using chokidar.watch()
function. {persistent: true}
indicates whether the process should continue to run as long as files are being watched.
– watcher.on('change')
is the event listener for a file changed event.
– in the handler, we use readLastLines()
to read the last line of the file, emit 'file-updated'
event with the content as message
.
– export Observer
module.
Use Observer object
Now we create server.js:
const Obserser = require('./services/observer');
var obserser = new Obserser();
const file = 'Performance/logs/info.log';
obserser.on('file-updated', log => {
console.log(log.message);
});
obserser.watchFile(file);
What we do:
– import Observer
class and initialize observer
object.
– use on()
method to listen 'file-updated'
event. In the handler, you can do anything such as: push alert message to chatwork, slack…
– call watchFile()
function.
Check result
On the project root folder, run this command:
node src/server.js
The console shows:
[8/29/2019, 10:22:35 PM] Watching for file changes on: Performance/logs/info.log
Now we add a new line to info.log
file, "new information here"
for example. Console will immediately show:
[8/29/2019, 10:24:36 PM] Performance/logs/info.log has been updated.
new information here
Conclusion
Today we’ve learned another way to listen/watch a file for changes by solving the real world problem: get the last line immediatly when it is added.
With the previous post: How to watch folder for changes in Node.js, we hope you have more ways to work with folder/file changes.
Happy learning! See you again.
Further Reading
- https://www.npmjs.com/package/chokidar
- https://github.com/paulmillr/chokidar
- https://www.npmjs.com/package/read-last-lines
Source Code
You can find the complete source code for this example on Github.
Hi.
Thanks for this great article. I need to monitor a directory for new log files created or added. this part is fine. i need my react app to receive this info real time. what would be the best way to do this? is send server event the best method to send new log aaded event to react app? is there any other best way to do it?
Hi, thank you for the clear explanation. Please make more tutorials about Node.js File.