Search code examples
javascriptes6-promise

When a library doesn't return promises, how can I use Promise.all to wait for the callbacks to be done?


fs.readdir doesn't seem to return a promise. So in a situation like this, how can I apply a promise-like approach for avoiding "indent hell"?

let tasks = []
fs.readdir(testDir, (err, files) => {
  files.forEach((file) => {
    console.log("file", file);
    // do stuff
  });
  // tasks[0].resolve() // I was trying to create promises to pass to tasks and then resolve
  // but couldn't figure out how to do it neatly.
});
console.log('tasks', tasks)

fs.readdir(trainDir, (err, files) => {
  files.forEach((file) => {
    console.log("file", file);
    // do stuff
  });
  // tasks[1].resolve()
});
Promise.all(tasks).then(() => {
    console.log('tasks done')
})

Obviously I could just trigger each progressive step as another callback:

fs.readdir(testDir, (err, files) => {
  files.forEach((file) => {
    console.log("file", file);
    // do stuff
    fs.readdir(trainDir, (err, files) => {
      files.forEach((file) => {
        console.log("file", file);
        // do stuff
      });
      console.log('tasks done')
    });
});

But Promises were made to avoid this indention pattern. So how do I use them here?


Solution

  • fs.promises in any reasonably recent version of Node will give you promisified versions of each fs function.

    const fs = require('fs').promises;
    Promise.all([
        fs.readdir(testDir).then((files) => {
            // ...
        }),
        fs.readdir(trainDir).then((files) => {
            // ...
        })
    ])
        .then(() => {
            console.log('tasks done')
        })
        .catch((err) => {
            console.log('encountered error')
        });