Disclaimer: I am trying to learn, so question may be (an probably is) trivial; any comment on better ways to do the same are welcome, but I need to understand underlying concepts.
I am more of a python programmer, so async
/await
is somewhat familiar, while Promise is a rather new concept.
I have a simple Node.js program scanning a subdirectory and doing stuff with filenames:
const chalk = require('chalk');
const ProgressBar = require('progress');
const fs = require('fs');
const path = require('path');
async function* walk(dir) {
for await (const d of await fs.promises.opendir(dir)) {
const entry = path.join(dir, d.name);
if (d.isDirectory()) yield* await walk(entry);
else if (d.isFile()) yield entry;
}
}
async function scan(cb) {
var docs = [];
for await (const p of walk('docs')) {
if (p.endsWith('.md')) {
console.log(p);
docs.push(p);
}
}
docs.sort();
if (cb)
cb(docs);
}
async function inspect(docs) {
const bar = new ProgressBar(':bar', { total: docs.length });
for (f in docs) {
if (bar.curr === 0) {
console.log(chalk.green('starting...'));
}
bar.tick();
// do other work and (possibly) modify `docs` array
if (bar.complete) {
console.log(chalk.green('done.'));
}
}
// pass docs to next stage
}
scan(inspect)
Since the chain will be much longer than this (I need to read files, order them according to content, build a TOC, etc.) I thought to modify it to use promises to resemble something like:
scan('/my/dir/to/scan')
.then(inspect)
.then(generate, `/path/to/target/file/`)
.catch(printError)
But I couldn’t find a way to do it (I saw several answers on the subject, but I couldn’t find a real answer to my question).
2
Answers
What do you want to do? What isnt working?
At a quick glance, this seems like a fine use of await. The await keyword halts at that line until the promise resolves or rejects. The then() doesnt halt the program, but runs the callback whenever the promise resolves. The catch() does the same, but for the reject case of the promise.
Perhaps your program exits without awaiting the scan()… call? Just put await in front of it, if your Node.js version supports "top level await". Otherwise there is another trick to do the same.
I would suggest, you should not call the callback functions directly from other functions. Instead, keep your functions simple and return the output. Create a parent function and call all the functions line by line using
await
keyword and pass the output. Refer below code: