Suppose we wanted some sort of feedback, to show that the process was doing something.
We could use an interval to write a dot to process.stdout every 10 ms.
Suppose we add the following to the top of the file:
setInterval(() => process.stdout.write('.'), 10).unref()
This should queue a function every 10 ms that writes a dot to STDOUT.
The unref method may seem alien if we're used to using timers in the browser.
Browser timers (setTimeout and setInterval) return numbers, for IDs that can be passed into the relevant clear function. Node timers return objects, which also act as IDs in the same manner, but additionally have this handy unref method.
Simply put, the unref method prevents the timer from keeping the process alive.
When we run our code, we won't see any dots being written to the console.
This is because the synchronous operations all occur in the same tick of the event loop, then there's nothing else to do and the process exits. A much worse scenario is where a synchronous operation occurs in several ticks, and delays a timer (or an HTTP response).
Now that we want something to happen alongside our operations, we need to switch to using asynchronous file methods.
Let's rewrite our source file like so:
setInterval(() => process.stdout.write('.'), 10).unref()
const fs = require('fs')
const path = require('path')
const cwd = process.cwd()
fs.readFile(path.join(cwd, 'file.dat'), (err, bytes) => {
if (err) { console.error(err); process.exit(1); }
const clean = bytes.filter(n => n)
fs.writeFile(path.join(cwd, 'clean.dat'), clean, (err) => {
if (err) { console.error(err); process.exit(1); }
fs.appendFile(
path.join(cwd, 'log.txt'),
(new Date) + ' ' + (bytes.length - clean.length) + ' bytes
removed\n'
)
})
})
Now when we run our file, we'll see a few dots printed to the console. Still not as many as expected - the process takes around 200 ms to complete; there should be more than 2-3 dots! This is because the filter operation is unavoidably synchronous and quite intensive; it's delaying queued intervals.