Search code examples
javascriptnode.jsrequirejsamd

Require: access/list all loaded modules


I'm in the situation where I have the following code:

define([
    "require",
    "./module1/module1",
    "./module2/module2",
    "./module3/module3",
    // ...
    // hundreds of modules here (with their path)
    // ...
], function (
    require,
    module1,
    module2,
    module3,
    // ...
    // hundreds of modules's name here
    // ...
) {
    var myMod = function() {

        myMap = {                            |
            "module1": new module1(),        | This is the part
            "module2": new module2(),        | I would like to
            "module3": new module3()         | optimize.
        }                                    |

    return myMod;
});

Here for each loaded module, I initialize it and push into a map. Of course the code above is not readable, maintainable and horrible.

Instead I want to do something like below:

define([
    "require",
    // ...
    // hundreds of modules here (with their path)
    // ...
], function (
    require,
    // ...
    // hundreds of modules's name here
    // ...
) {
    var myMod = function(myDict) {

        myMap = {}

        for (var elem in myDict) {
            ***myMap[elem.name] = new $corresponding-elem-referece$();*** // pseudo-code.
        }


    return myMod;
});

Basically, each of elements within myDictdictionary has a name property. Depending of the value of name I want to initialize the corresponding module and add the result into myMap object. In order to do that, I should be able to get the module reference knowing its name. And here lives my problem - I think.

This is useful to me because in this way I do not need to initialize all modules and push them into the map, if I'm not gonna use them - kind of lazy loader.

Any help or suggestion? Thanks.


Solution

  • You could scan arguments to build your map. Here is an example designed to run as-is in Node.js. Comments in the code explain what is going on.

    var requirejs = require("requirejs");
    
    var req = requirejs({});
    
    function generic_module(module) {
        function m() {
            // Convenience so that we can distinguish instances...
            this.from_module = module.id;
        };
    
        // Set an `id` property on the function we return so that we can
        // match by module id rather than function name. Module.id is the
        // name by which the module is known to RequireJS.
        m.id = module.id;
    
        return m;
    }
    
    requirejs.define('a', ['module'], generic_module);
    requirejs.define('b', ['module'], generic_module);
    requirejs.define('c', ['module'], generic_module);
    
    requirejs.define('test', ['require', 'a', 'b', 'c'], function () {
    
        // Create a map from module name to module value. We use the `id`
        // field we set on the module's return values to be able to map by
        // module id instead of function name.
        var name_to_value = Object.create(null);
        for (var i = 1; i < arguments.length; ++i) {
            var arg = arguments[i];
            name_to_value[arg.id] = arg;
        }
    
        // The myDict value should be a dictionary whose keys are module
        // ids.
        function myMod(myDict) {
            var keys = Object.keys(myDict);
    
            var myMap = Object.create(null);
            for (var i = 0; i < keys.length; ++i) {
                var key = keys[i];
                var value = name_to_value[key];
                myMap[key] = new value();
            }
    
            return myMap;
        }
    
        return myMod;
    });
    
    req(['test'], function (test) {
        console.log(test({'a': 1, 'b': 1}));
    });