0

So, I have had a problem recently!

I was trying to assign a value to a variables value (a little confusing, i know). I was trying to make a library system for my Discord bot, which uses JavaScript (Node.js)!

So, here's a part of the code that I was struggling with:

    flist.forEach(item1 => {
        liblist.forEach(item => {
            eval(item1 = require(item));
        });
    });

OK, so basically item1 has to be replaced with a library file's name (if a file is named cmdh, I use that as a variable name to assign require(item) to it)

Edit: the item1 is the file name, by the way.

Edit 2: Here's a part of the file util.js:

const Discord = require("discord.js");
const fs = require("fs");
function genEmbed(title, desc, col) {
    return new Discord.MessageEmbed().setTitle(title).setDescription(desc).setColor(col);
};
function log(inp) {
    console.log(`[UTIL] ${inp}`);
};

function loadDef() {
    log("Loading libraries...");
    dirlist = [];
    liblist = [];
    flist = [];
    fs.readdir("./libraries", (err, dirs) => {
        if(err) console.error(err);
        dirs.forEach(dir => {
            dirlist.push("./libraries/" + dir); 
        });
        dirlist.forEach(dir => {
            fs.readdir(dir, (err, files) => {
                if(err) console.error(err);
                files.forEach(file => {
                    if(file.includes(".")) {
                        liblist.push(require(dir + "/" + file));
                        filename = file.split(".")[0];
                        flist.push(filename);
                    } else {
                        log(`${file} is a directory, ignoring...`)
                    };
                });
            });
        });
    });
    flist.forEach(item1 => {
        liblist.forEach(item => {
            eval(item1 = require(item));
        });
    });
    log("Libraries loaded!");
};

module.exports = {
    genEmbed,
    loadDef
};
TheRed
  • 61
  • 2
  • 9

1 Answers1

1

If you are trying to assign a new value for each element in an array and return a new array with the updated values, you should use map instead of forEach.

If you want to return an array with the required libraries from liblist and store the result in flist, your code should look as follows:

    flist = liblist.map(item => require(item));

Essentially, map takes each value from an array, applies a function to it (in your case, require), and then returns a new array with the results of the function.

It should be noted that you also need to replace fs.readdir with fs.readdirSync, otherwise liblist will be empty when the code is called.


After our discussion on the chat I understood that you want to set the variables as globals in your main file. However, this is a bit hackish. To do that you need to modify the global object.

Note: I would advise you to statically require via const libraryName = require('./libraries/fileName.js') instead, as this way of dynamically defining libraries has no advantage in this case and only makes the code more complicated. Dynamically requiring libraries only makes sense when you, for example, add listeners via your libraries, but then you do not need to store them as globals.

Your full code for the utils file should now look as follows:

const Discord = require("discord.js");
const fs = require("fs");
function genEmbed(title, desc, col) {
    return new Discord.MessageEmbed().setTitle(title).setDescription(desc).setColor(col);
};
function log(inp) {
    console.log(`[UTIL] ${inp}`);
};

function loadDef() {
    log("Loading libraries...");
    libraries = {};
    const dirlist = fs.readdirSync("./libraries").map(dir => "./libraries/" + dir)
    dirlist.forEach(dir => {
        const files = fs.readdirSync(dir)
        files.forEach(file => {
            if(file.includes(".")) {
                filename = file.split(".")[0];
                libraries[filename] = require(dir + "/" + file);
            } else {
                log(`${file} is a directory, ignoring...`)
            };
        });
    });
    log("Libraries loaded!");
    return libraries;
};

module.exports = {
    genEmbed,
    loadDef
};

Now you still need to modify the code in your main file, as follows:

const libraries = loadDef()
global = Object.assign(global, libraries) // assign libraries to global variables
omnidan
  • 1,162
  • 2
  • 12
  • 25
  • I have like no idea how to use it, can you please give me the code of the fixed file? – TheRed Mar 20 '20 at 11:53
  • 1
    @MantvydasViršilas you just have to replace the code snippet you posted above with the code snippet here. I will edit my post to show the full file as well. – omnidan Mar 20 '20 at 11:55
  • 1
    It should be noted that you also need to replace `fs.readdir` with `fs.readdirSync`, otherwise `liblist` will be empty when the code is called. – omnidan Mar 20 '20 at 11:58
  • 1
    @MantvydasViršilas did you replace `fs.readdir` with `fs.readdirSync`? – omnidan Mar 20 '20 at 11:59
  • I also replaced the code lines, didnt work either (the readdirSync) – TheRed Mar 20 '20 at 12:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/209996/discussion-between-omnidan-and-mantvydas-virsilas). – omnidan Mar 20 '20 at 12:00
  • @MantvydasViršilas please give some information on what exactly does not work - what is the expected output, and what happened? – omnidan Mar 20 '20 at 12:01