0

I've tried implementing the code from here, but I have problem with asynchronous function.

I wanted to get a folder map through a function like this:

getFolderMap("./public", function(folderMap){
    /* Call back */
});

And the function would return sth. like this:

{
    "index":{"fileType":"html", blah blah blah...}
    "assets":{
        "plants":{
            "plant1":{"fileType":"png", blah blah blah...}
        }
    }
    "css":{
        "style":{"fileType":"css", blah blah blah...}
        "flickity":{"fileType":"css", blah blah blah...}
    },
    "js":{
        "main":{"fileType":"js", blah blah blah...}
    }
}

The code was:

var getFolderMap = function(rootDir, cb) { 
    fs.readdir(rootDir, function(err, files) { 
        var dirs = {};
        for (var index = 0; index < files.length; index++) { 
            var file = files[index]; 
            if (file[0] !== '.') { 
                var filePath = rootDir + '/' + file; 
                fs.stat(filePath, function(err, stat) {
                    if (stat.isDirectory()) {
                        var file = this.file;
                        //Recursion...
                        getFolderMap(this.filePath,function(d){
                            dirs[file]=d;
                        });
                    }else{
                        dirs[this.file] = {
                            fileType: ""
                        };
                    }
                    if (files.length === (this.index + 1)) { 
                        return cb(dirs); 
                    } 
                }.bind({index: index, file: file, filePath:filePath})); 
            }
        }
    });
};
5
  • 3
    Can you share your code? And what error are you running into? Commented Feb 14, 2021 at 5:52
  • There's no error, but the result is returned before the handeler is called. Commented Feb 14, 2021 at 6:15
  • can you use for of with async/await instead of for with callback? @猫ハッカー Commented Feb 14, 2021 at 6:32
  • Never herd of for ... of loop before... let me check it. I'm self-taught, so I don't know much about these rare keywords. Commented Feb 14, 2021 at 6:37
  • Both for ... in and for ... of doesn't work. Huh? Commented Feb 14, 2021 at 6:40

2 Answers 2

1

You can use async/await and Promise.all to simplify the orchestration of the async operations.

const { readdir, stat } = require('fs').promises
const { extname } = require('path')

const generateFolderMap = async (rootDir) => {
  const files = await readdir(rootDir)

  const map = {}
  await Promise.all(
    files.map(async (file) => {
      if (file[0] === '.') {
        return null
      }

      const filePath = rootDir + '/' + file
      const stats = await stat(filePath)

      if (stats.isDirectory()) {
        map[file] = await generateFolderMap(filePath)
      } else {
        map[file] = { fileType: extname(file).slice(1) }
      }
    })
  )

  return map
}
Sign up to request clarification or add additional context in comments.

2 Comments

I got an error UnhandledPromiseRejectionWarning: ReferenceError: Cannot access 'readdir' before initialization
@猫ハッカー Can you share your code in a gist or something?
0

I've decided that I'd be using the synchronous version, and it works perfectly. Though it made the server starting up pretty slowly. It's not a big problem though, I just wanted to find the best solution to my problem to speed up my server.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.