1

I have this code which loops through all directories in the folder commands and then loops through each file in each of those directories. It then imports the module, converts it to JSON and adds it to an array called commands and a map called client.commands.

let commands = [];
client.commands = new Map();
fs.readdir(__dirname + "/../commands/", (err, dirs) => {
    if (err) return console.error(err);
    for (let dir of dirs) {
        fs.readdir(__dirname + `/../commands/${dir}/`, (err, files) => {
            if (err) return console.error(err);
            for (let file of files) {
                let command = require(`../commands/${dir}/${file}`);
                commands.push(command.data.toJSON());
                client.commands.set(command.data.name, command);
                console.log(commands);
            }
        });
    }
});
console.log(commands);

If I console.log the value of commands in the inner most for loop, the output is exactly as expected. However, if I log it on the outside of the entire code block, it just prints an empty list.

SirArchibald
  • 476
  • 2
  • 7
  • 23
  • 2
    One word: Asynchronous – Ram Dec 10 '21 at 16:46
  • 1
    Two words: Use `readdirSync()` – Randy Casburn Dec 10 '21 at 16:49
  • 1
    @RandyCasburn I'd suggest using promises. Node `fs` module has builtin APIs for promises. https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_fs_promises_api – Ram Dec 10 '21 at 16:55
  • @RandyCasburn generally speaking it's best avoided. Might be ok for simple console functions, but if you do that in a multi-user web server for example it's not a great idea. – Keith Dec 10 '21 at 16:57
  • @undefined There is nothing diabolical or evil or terrible about doing work synchronously. There are actually use cases in which it is desired. Bottom line - it is a viable solution that works. The OP can choose. – Randy Casburn Dec 10 '21 at 16:58
  • @Keith - This is a file reader that does data transformation. The use case is plain to see. Nothing wrong with sync here. – Randy Casburn Dec 10 '21 at 16:59
  • 2
    @RandyCasburn There is nothing in the OP's code to suggest this couldn't be used in say an express app. And if it was, it going to block requests. And I did say, might be OK for simple console apps. – Keith Dec 10 '21 at 17:00
  • @Keith and there is nothing that says that it is - as I said, the OP can choose. – Randy Casburn Dec 10 '21 at 17:01
  • 1
    @RandyCasburn Then why make an assumption, if the OP uses promises, we don't even need to make that distinction. Not sure why your getting umpty about it, especially as I put a proviso that it's maybe OK for simple console apps. – Keith Dec 10 '21 at 17:05
  • I think DerEchteKroate has the point on this. Looks like Discord. If so, Op should tag question as such. – Randy Casburn Dec 10 '21 at 17:08

3 Answers3

0

I think you should use recursion to read the files inside the folders recursively. And below link the question that already asked I think will help to solve this. Node.js fs.readdir recursive directory search

Anar Ahmad
  • 66
  • 6
0

This looks like discord.js to me.

client.commands = new Discord.Collection();

const commandFiles = fs.readdirSync("./commands").filter(file => file.endsWith(".js"));

for (const file of commandFiles) {
    const command = require(`.commands/${file}`);
    client.commands.set(command.name, command);
}

Your commands should look like this

module.exports = {
    name: "name",
    description: "description",
    execute() {
    // execution code
    }
}

You can then use it by calling the function or getting the variables

client.commands.get(/* Name of command */).execute();
Kalle
  • 150
  • 6
0

since readdir() is asynchrose, your outer console.log() is called before the function in the middle is fully executed.

I adjusted the syntax to the more modern async and await since fallback functions are not the best Practice anymore, unfortunately I couldn't test it, but it is atleast the correct way to go ;)

let commands = [];
client.commands = new Map();

async function main() {
    try {
        const dirs = await fs.readdir(__dirname + "/../commands/")
        for (let dir of dirs) {
            const files = await fs.readdir(__dirname + `/../commands/${dir}/`)
            for (let file of files) {
                let command = require(`../commands/${dir}/${file}`);
                commands.push(command.data.toJSON());
                client.commands.set(command.data.name, command);
                console.log(commands);
            }
        }
    } catch (error) {
        console.error(err)
    }

    console.log(commands);
}

main()
Branchverse
  • 1,203
  • 1
  • 7
  • 19