Dynamic loading of modules from array using RequireJS - javascript

I am working on an application using RequireJS AMD loading method.
I have my modules dynamical picked up from a configuration file into an array
var amd_modules = ["module1", "module2","module3"]
now I have my requireJS code
require(amd_modules, function(result) {
console.log("All modules loaded");
}
Now, the result variable shows the first module which is "module1". How can I get other modules also into variable inside the function() parenthesis.
For eg,
require(amd_modules, function(module1, module2, module3) { //
}
I can't write the above hardcoding because the number of dynamic variables are not known until run time. Do let me know how I can catch the objects dynamically inside the function.
Thx

Simply use arguments:
require(amd_modules, function() {
console.log("All modules loaded");
// arguments should now be an array of your required modules
// in the same order you required them
});
However, unless you have a good reason to do so, you probably want to rethink the way you are designing your application - even at the topmost level your modules should be simple and testable. Having a widely varying number of dependencies indicates that you are probably trying to do to much in your callback function. Break each code path out into its own module and then switch only on your top-level dependency instead. In code:
// Instead of this:
require(amd_modules, function() {
console.log("All modules loaded");
if (complex_condition_A) {
var x = arguments[0],
y = arguments[1],
z = arguments[2];
// Do things with x, y and z
}
else if (complex_condition_B) {
var a = arguments[0],
b = arguments[1];
// Do things with a and b
}
else {
// et cetera, et cetera, et cetera
}
});
// Do this instead
var rootModule;
if (complex_condition_A) rootModule = "A";
else if (complex_condition_B) rootModule = "B";
else rootModule = "C";
require(rootModule, function(root) {
// Root has the same API, regardless of which implementation it is
// This might be as simple as an `init` method that does everything
// or as complex as, say Facebook's API, but with different libraries
// loaded depending on the platform the page is loaded on
// (IE vs. Android for example).
});

Try something like this:
define(function () {
var ClassLoader = function () {
var _construct = function () {
return _public;
},
_loadClass = function (className, callback) {
//
require([className],
function (LoadedClass) {
callback(LoadedClass);
});
},
_public = {
loadClass: _loadClass
};
return _construct();
}
return ClassLoader;
});

Related

Function chaining with function names from list [duplicate]

What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects

Modifying variables in subclass instances

I've become hopelessly addicted to Screeps recently, and I refactored some code to make a task-based implementation. Tasks are things like "walk to and then harvest until you are at full capacity" and are based off of a single base task template written as an ES6-style class. Creeps can be assigned tasks through a wrapper (tasks.js) that loads the relevant task file and returns a new task instance.
Today I ran into a strange bug that makes me think I don't fully understand Javascript's inheritance model. Below is the relevant code:
Task.js: (base task class)
class Task {
constructor(taskName) {
// Parameters for the task
this.name = taskName; // name of task
this.quiet = false; // suppress console logging if true
this.creep = [creep assigned to this task]
this.target = [thing task operates on, e.g. "repair this wall"]
...
}
...
// Execute this task each tick. Returns nothing unless work is done.
step() {
...
if (creep.pos.inRangeTo(target, this.targetRange)) {
var workResult = this.work();
console.log(this.quiet) // < returns false, should be true?
if (workResult != OK && this.quiet == false) {
creep.log("Error: " + workResult); // < is printed when run
}
return workResult;
} [else move to target]
}
...
// Task to perform when at the target
work() {
// overwrite this in child class
}
}
module.exports = Task;
task_harvest.js: (harvesting task)
var Task = require('Task');
class taskHarvest extends Task {
constructor() {
super('harvest');
// no mention of this.quiet here
}
...
work() {
console.log("harvest:" + this.quiet);
return this.creep.harvest(this.target);
}
}
module.exports = taskHarvest;
tasks.js: (wrapper to generate a new task instance via a function call)
module.exports = function (taskName) {
var TaskClass = require('task_' + taskName); // all tasks follow this naming pattern
var taskInstance = new TaskClass;
return taskInstance;
};
harvester.js: (behavior model for a harvester creep)
var tasks = require('tasks');
var roleHarvester = {
...
harvest: function (creep) {
var target = Game.getObjectById(creep.memory.assignment);
var taskHarvest = tasks('harvest');
taskHarvest.quiet = true; // < this task shouldn't print anything
creep.assign(taskHarvest, target); // assigns to creep.task
return OK;
},
...
run: function (creep) { // executed every tick
// execute the task
creep.task.step();
},
...
}
When I assign a creep to harvest from a source, I create a new task from task_harvest.js, set its quiet property to be true, and bind it and its target to the creep. Once the creep has a task it is instructed to run it until it becomes invalid (code not included above). The creep executes the task fine, but it still logs everything to the console.
I would think that in harvester.js, when I set taskHarvest.quiet = true;, the behavior imported from Task.js would see this.quiet as true. However, it seems as though that is not the case. In roleHarvester, running console.log(creep.task.quiet) returns true, but in Task, running console.log(this.quiet) when the creep is executing the assigned task gives false.
I could add quiet into the constructor as an optional parameter, but that's convoluted and I want to know why what I'm doing isn't working.
Nevermind, it actually wasn't an inheritance problem; it was a problem caused by the game mechanics: taskHarvest.quiet wasn't getting deleted each tick. Screeps only allows you to store JSON-serializable objects in memory, so I store the task settings in memory and reconstruct the task object each tick:
Object.defineProperty(Creep.prototype, 'task', {
get: function () { // provide new task object recreated from literals stored in creep.memory.task
if (this.memory.task != null) {
var task = tasks(this.memory.task.name);
task.creepName = this.memory.task.creepName;
task.targetID = this.memory.task.targetID;
task.data = this.memory.task.data; // < task.quiet is now task.data.quiet
return task;
} else {
return null;
}
},
set: function(newTask) {
if (newTask != null) {
this.log("use Creep.assign() to assign tasks. Creep.task = ___ should only be used to null a task.");
} else {
this.memory.task = newTask;
}
}
});
taskHarvest.quiet wasn't getting stored in memory, so it wouldn't persist past the first tick of the task. I now store all instance-level adjustable parameters in a task.data object, so task.quiet is now task.data.quiet. This fixed the problem; sorry for producing any confusion!

How to create javascript function constructor with default functionality and persistent properties?

I've got a slightly unusual pattern I'm trying to achieve and have not quite figured it out. My goal is to create a function called debugLog as a flexible console.log replacement, which can be called as follows:
debugLog('thing to log #1', 'thing to log #2', objectToLog1, objectToLog2);
^^ the number of params should be arbitrary, just as is possible with console.log
That is what I'll call the "default" functionality. Now I'd also like to add some additional functionality through property functions.
Examples:
debugLog.setDebugFlag(true); // sets the internal this.debugFlag property to true or false depending on param
I'm trying to do this in Node and what I have so far does not quite let me achieve this pattern:
var debugLog = function () {
this.debugFlag = this.debugFlag || true;
if (this.debugFlag) {
console.log.apply(null, arguments);
} else {
// production mode, nothing to log
}
};
debugLog.prototype.setDebugFlag = function (flagBool) {
this.debugFlag = flagBool;
}
module.exports = new debugLog();
This module would be including in a Node app using the standard require pattern:
var debugLog = require('./debugLog.js');
The question is how can I achieve this pattern of a function object with default functionality, but also extended "property" style functions? Please note I am already aware of the typical pattern where ALL functionality comes from function properties (such as debugLog.log() and debugLog.setDebugFlag()). But that patterns does NOT achieve my key goal of a shorthand for the default functionality that simply involves calling the function directly.
Is it even possible to do?
You could do it this way
var debugLog = (function() {
var debugFlag = true;
function log() {
if (debugFlag) {
console.log.apply(null, arguments);
} else {
// production mode, nothing to log
}
};
log.setDebugFlag = function(flag) {
debugFlag = flag;
}
return log;
})();
module.exports = debugLog;
You could use closure, like so:
// debugLog.js
var debugFlag = true;
function debugLog() {
if (debugFlag) {
console.log.apply(null, arguments);
} else {
// production mode, nothing to log
}
}
debugLog.setDebugFlag = function (newFlag) {
debugFlag = newFlag;
}
module.exports = debugLog;
and use it like this:
// otherFile.js
var debugLog = require('./debugLog');
debugLog('Hey!');
debugLog.setDebugFlag(false);
debugLog('This wont appear!');

Durandal: one compositionComplete to rule them all

With Durandal we have the compositionComplete event for last minutes processing on the view.
Currently my view composition hierarchy is quite complex, and I need to do various UI processing at different point in the app.
To avoid calling multiple times the same UI related code, and to guarantee it will be called at least once when some view needs it, I need a finalCompositionComplete() hook somewhere.
I didn't find such an event in the current Durandal implementation so I was thinking of adding it to the composition.js file (I figured out the endComposition() function would be a good place to start...)
It's obviously a bad idea modifying original durandal files for maintenance reasons.
Is there a better solution? One that is more maintenance friendly..
What I've done so far (and seems to be working):
created a lifecycle plugin in the plugins directory of durandal (and injected it in the composition module)
modified the composition.js file's endComposition() function
Now I can register callbacks through my lifecycle plugin and it will be called once at the very end
The endComposition() function in the composition.js file:
function endComposition() {
compositionCount--;
if (compositionCount === 0) {
setTimeout(function(){
var i = compositionCompleteCallbacks.length;
while(i--) {
try{
compositionCompleteCallbacks[i]();
}catch(e){
system.error(e);
}
}
// my modification is right here:
lifecycle.finalCompositionComplete();
compositionCompleteCallbacks = [];
}, 1);
}
}
lifecycle plugin
define(['durandal/system', 'underscore'], function (system, _) {
var _nameCounter = 0;
var _processes = {};
return {
registerFinalProcess: register,
finalCompositionComplete: processFinal
};
function register(processName, callback) {
processName = processName || '_noname' + _nameCounter++;
_processes[processName] = callback;
}
function processFinal() {
_.each(_.pairs(_processes), function(pair) {
try {
if (typeof pair[1] === 'function') {
pair[1]();
}
delete _processes[pair[0]];
} catch(e) {
system.log('error:could not call ' + pair[0]);
}
});
_processes = {};
_nameCounter = 0;
}
});
Anywhere, anytime in my app:
lifecycle.registerFinalProcess('someCallbackId', someFunction);

Equivalent of "window["functionName"](arguments)" in server-side

What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects

Categories