Tuesday, May 21, 2024
 Popular · Latest · Hot · Upcoming
62
rated 0 times [  68] [ 6]  / answers: 1 / hits: 128712  / 11 Years ago, wed, july 3, 2013, 12:00:00

Is there a way to define a module that dynamically load other modules in RequireJS? If yes, how the optimizer (r.js) understands how/when a module has to be included?



For example, let dynModules a module which defines name/path pairs:



define([], function () {
return ['moduleA', 'moduleB']; // Array of module names
});


Another module is going to load modules dynamically, based on the array. This will not work:



define(['dyn_modules'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}

// ...
});


... gives me:




Uncaught Error: Module name moduleA has not been loaded yet for
context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded




I can solve the error, but it's not dynamic anymore:



define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}

// ...
});

More From » browser

 Answers
306

The limitation relates to the simplified CommonJS syntax vs. the normal callback syntax:





Loading a module is inherently an asynchronous process due to the unknown timing of downloading it. However, RequireJS in emulation of the server-side CommonJS spec tries to give you a simplified syntax. When you do something like this:



var foomodule = require('foo');
// do something with fooModule


What's happening behind the scenes is that RequireJS is looking at the body of your function code and parsing out that you need 'foo' and loading it prior to your function execution. However, when a variable or anything other than a simple string, such as your example...



var module = require(path); // Call RequireJS require


...then Require is unable to parse this out and automatically convert it. The solution is to convert to the callback syntax;



var moduleName = 'foo';
require([moduleName], function(fooModule){
// do something with fooModule
})


Given the above, here is one possible rewrite of your 2nd example to use the standard syntax:



define(['dyn_modules'], function (dynModules) {
require(dynModules, function(){
// use arguments since you don't know how many modules you're getting in the callback
for (var i = 0; i < arguments.length; i++){
var mymodule = arguments[i];
// do something with mymodule...
}
});

});


EDIT: From your own answer, I see you're using underscore/lodash, so using _.values and _.object can simplify the looping through arguments array as above.


[#77226] Tuesday, July 2, 2013, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
erick

Total Points: 588
Total Questions: 92
Total Answers: 100

Location: Bangladesh
Member since Sat, Jan 23, 2021
3 Years ago
;