How do i optimise multiple require() call?

111 Views Asked by At

I'm making a bot for the mattermost server of my company (like a discord bot), and for my bot commands, I created one file per command.

The idea is that to send a command, the user must send a message like "!giveChannelPerms arg1 arg 2 ...". The bot will parse the message to identify the command (in this case !giveChannelPerms) and execute the code related to the command.

The problem is that for each command, I have to require() the file and make an if {} else if {} else if {} ... to find the command, as you can see with the code below.

const giveChannelPerms = require('../cmd/giveChannelPerms');
const removeChannelPerms = require('../cmd/removeChannelPerms');

[...]

if (cmd == "!giveChannelPerms") {
    giveChannelPerms.giveChannelPerms(post, args, db, obj);
} else if (cmd == "!removeChannelPerms") {
    removeChannelPerms.removeChannelPerms(post, args, db, obj);
}

This code is good if we only have 2 commands for our bot, but the more commands I create, the more require() and if {} else if {} will be big.

Isn't there a more "optimized" way to do what I'm trying to do? I had thought of doing something like C function pointers but I have no idea how to do it.

4

There are 4 best solutions below

4
On BEST ANSWER

If you want less require and reduce if elses, I recommend you to create a file importing your commands and returning an associated map

const { giveChannelPerms } = require('../cmd/giveChannelPerms');
const { removeChannelPerms } = require('../cmd/removeChannelPerms');

const cmdMap = new Map();

cmdMap.set('!giveChannelPerms', giveChannelPerms)
cmdMap.set('!removeChannelPerms', removeChannelPerms)

export default cmdMap

Then you will be able to import it only once and use it without conditions in your file :

// Imported multiples functions in one require
const commands = require('../cmd/commands');

// Will execute function associated to cmd string without conditions
commands.get(cmd)(post, args, db, obj);
2
On

Maybe something like this would work

[...]
require('../cmd/giveChannelPerms').then(res => { 
    if (res) {
        res.giveChannelPerms(post, args, db, obj);
    } else {
        require('../cmd/removeChannelPerms').then(rslt =>  {
             if (rslt) rslt.removeChannelPerms(post, args, db, obj);
        })
    }
});
  
2
On

Borrowing from https://stackoverflow.com/a/38397640/932256 try:

const commandFiles = {
    giveChannelPerms: require('../cmd/giveChannelPerms'),
    removeChannelPerms: require('../cmd/removeChannelPerms')
};

const commandList = Object.keys(commandFiles);

if (cmd.match(new RegExp('^!(' + commandList.join('|') + ')$'))) {
    let baseCommand = cmd.replace('!', '');
    commandFiles[baseCommand][baseCommand](post, args, db, obj);
}

Now all you need to do is add your commands to the commandFiles object.

1
On

I think you are looking for below two solution, hope this helps

  1. More elegant way to manage your imports - For this you can create a index file (index.js) which will import all your commands from different file and export all commands from one place which is index.js
  2. Simplify your if else condition - from your code snippet, it seems like you need to evaluate against each command as the code then executed is different for each command. As there is no escape from, switch-case will provide you better code readability than if-else
const Cmds = require('../cmd/index');
// or you use import as below
//const {giveChannelPerms, removeChannelPerms} = require('../cmd/index')

switch(cmd)
case: '!giveChannelPerms'
   Cmds.giveChannelPerms.giveChannelPerms(post, args, db, obj);
case: '!removeChannelPerms' 
    Cmds.removeChannelPerms.removeChannelPerms(post, args, db, obj);
defualt:
     // do-somthing
}