Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Dynamically execute arrow function from within 'master' arrow function?

1715174248
Coryphon
Pro
Sheet Author
Compendium Curator
Hi there, I'm trying to do the following, but not sure of the syntax: const MassCombatRules = (() => { const myCommand = (msg, args) => { // Do stuff } /* * */ const handleInput = (msg) => { let args = msg.content.split(/\s+/); if (args[ 0 ] === "!mcr" ) { log( "Running command: " + args[ 1 ]); // If args[1] is a function in MassCombatRules look it up and execute it, the below does not work if (MassCombatRules[args[ 1 ]]) { log( "Running command: " + args[ 1 ]); MassCombatRules[args[ 1 ]](msg, args); } else { log( "Unknown command: " + args[ 1 ]); } } }; on( "ready" , () => { on( "chat:message" , handleInput); }); })(); So is there a way to look up the myCommand arrow function (or any other) based on args[1]? Just want to avoid a whole switch or if-then-else-if. I kind of feel this should be possible but I think arrow functions and 'this' are somewhat complicated... Thanks in advance, ~ Coryphon ~
1715180172
timmaugh
Pro
API Scripter
Hey, Coryphon... yes, you can do that. Your args[1] is going to give you text, so once you've sanitized it, you can reference it as a property of another object. You can do that 2 ways that I can think of off the top of my head. Option 1 - Return the Function You Want to Run as Part of the Interface of Your Outer IIFE const MassCombatRules = (() => {     const myCommand = (msg, args) => {         // Do stuff     }     /*      *      */     const handleInput = (msg) => {         // ...snipping parsing the command line             if(MassCombatRules.hasOwnProperty(args[1]) && typeof MassCombatRules[args[1]] === 'function' ) {                 log("Running command: " + args[1]);                 MassCombatRules[args[1]](msg, args);             }             else {                 log("Unknown command: " + args[1]);             }         }     };     on("ready", () => {         on("chat:message", handleInput);     });     return {         MyCommand: myCommand     }; })(); Notice the interface returned at the end of the IIFE, and notice that your supplied arg would now have to match case with "MyCommand" since that is the name of the returned function (case altered to differentiate the internal function from the external interface). Option 2 - A Library Object Within the Outer IIFE A library object can connect a text property with a function. It operates much the same way as the returned interface, above, but doesn't require calling from dot notation on the outer IIFE name: const MassCombatRules = (() => {     const myCommand = (msg, args) => {         // Do stuff     }     /*      *      */     const funcLibrary = {         myCommand: myCommand,         default: (m,a)  => { log(`Unknown command: ${a[1]}`; }     };     const handleInput = (msg) => {         // ...snipping parsing the command line            funcLibrary[Object.keys(funcLibrary).filter(k => k === arg[1]).length ? arg[1] : 'default'](msg,args);         }     };     on("ready", () => {         on("chat:message", handleInput);     }); })(); I prefer this method if I don't actually need other scripts to have access to the inner functions of my IIFE.
1715180726
Coryphon
Pro
Sheet Author
Compendium Curator
Many thanks Timmaugh!
1715181370
timmaugh
Pro
API Scripter
No problem! Also, now that I think about it, you might be able to reduce that calling line from the second example to: funcLibrary[funcLibrary[arg[1]] ? arg[1] : 'default'](msg,args); ...but double check me on that.