Skip to content Skip to sidebar Skip to footer

Function Behaving Asynchronously Even After A Callback Function In Node.js

I am attempting to make a file explorer using the 'fs' module of Node.js. I wrote the following function which takes in a path and stores the contents of that path(files/folders) i

Solution 1:

The problem is that you're not waiting for the fs.lstat() function to finish for each file. You're queueing up all the fs.lstat() calls but then not waiting for all of them to finish. You're just going to return back resultObj when it is still [].

You can fix this by adding a check inside the callback of your data.forEach() to see how many of the items have had the callback for fs.lstat() invoked.

listDir: (path, myCallback) => {
    let resultObj = [];

    fs.readdir(path, (err, data) => {
      console.log('In listDir');
      if (err) {
          returnmyCallback(err);
      }

      let itemsCompleted = 0        
      data.forEach(value => {
        fs.lstat(path + '/' + value, (err, stats) => {
          itemsCompleted++
          if (err) {
            console.log(err);
          } else {
            if(stats.isFile() || stats.isDirectory()){
              resultObj.push(value);
              console.log(resultObj+'\n');
            }
          }

          if(itemsCompleted >= data.length) {
            returnmyCallback(null, resultObj)
          }
        });            
    });
}

However, the above approach is still more complicated than Promises with async/await. Promises with async/await is currently the preferred way to handle asynchronous control flow in Node. Utilizing util.promisify() to promisify fs.readdir() and fs.lstat() allows us to flatten the control flow and dramatically improve the readability of the listDir(). Additionally, by using map() instead of forEach() we can use Promise.all() to wrap the returned Promise from lstatAsync() for each entry.

const {promisify} = require('util')
const fs = require('fs')
const {join} = require('path')
const readdirAsync = promisify(fs.readdir)
const lstatAsync = promisify(fs.lstat)

module.exports = {
  listDir: async path => {
    let resultObj = []; 

    let entries = awaitreaddirAsync(path)
    console.log('In listDir');

    awaitPromise.all(entries.map(async value => {
      try {
        let stats = awaitlstatAsync(join(path, value))

        if(stats.isFile() || stats.isDirectory()){
          resultObj.push(value);
          console.log(resultObj+'\n');
        }
      } catch (err) {
        console.log(err)
      }
    }))

    return resultObj
  }
}

Post a Comment for "Function Behaving Asynchronously Even After A Callback Function In Node.js"