maxedison
maxedison

Reputation: 17573

Waiting until all promises have resolved while recursively walking a directory

I'm trying to recursively walk a directory tree and gather all the file names. In the following code, however, the console.log() at the end runs too early, not waiting for the promises generated by the function's recursive cacheDir call to resolve:

function cacheDir(dir) {
  return fs.readdir(dir).then(items => {
    const readDirPromises = []

    for (let item of items) {
      const fullPath = path.join(dir, item)
      const lstat = fs.lstat(fullPath)
      readDirPromises.push(lstat)

      lstat.then(stats => {
        if (stats.isFile()) {
          return fullPath
        } else {
          return cacheDir(fullPath)
        }
      })
    }

    return Promise.all(readDirPromises)
  })
}

cacheDir("../someDir/")
  .then(results => console.log('done!', results))

What am I doing wrong? It seems to me that readDirPromises will be an array of strings and promises, each promise of which will itself resolve to an array of strings and promises.

Upvotes: 2

Views: 127

Answers (1)

jfriend00
jfriend00

Reputation: 708206

The promise you wait on with Promise.all() needs to be lstat.then(), not just lstat. Remember that lstat.then() returns a new promise and that new promise tracks any promises returned from within the .then() handler which you need because of your recursion.

Here's a version that does that (and gets rid of some temporary variables):

function cacheDir(dir) {
  return fs.readdir(dir).then(items => {
    const readDirPromises = [];

    for (let item of items) {
      const fullPath = path.join(dir, item);

      readDirPromises.push(fs.lstat(fullPath).then(stats => {
        if (stats.isFile()) {
          return fullPath;
        } else {
          return cacheDir(fullPath);
        }
      }));
    }

    return Promise.all(readDirPromises)
  })
}

Upvotes: 3

Related Questions