简体   繁体   中英

Dynamic loading on modules from modules in requirejs

I'm using requirejs and have an app.js that pulls in framework.js and initializes it and passes in settings and modules with their own settings. Problem is $('[data-navigation]').navigation(); is triggering before the navigation module, which is a jQuery plugin, is ready. If I add around a 500ms delay it works.

require(['jquery-private', 'framework', 'navigation'],
function($, framework, navigation) {

    //==========
    // Initialize the framework core.
    //==========
    var core = framework.init({
        // Core settings.
        namespace: '',

        // Initialize modules.
        modules: {
            navigation: {
                openClass: 'open',
            },
        },
    });

    //==========
    // App logic.
    //==========
    $('[data-navigation]').navigation();
});

Here is how the modules are initialized. I think the problem is happning with this require([moduleName], function(module) {} running while the script continues on.

define(['jquery', 'matchmedia'], function($) {

    //==========
    // Core initialization object.
    //==========
    var init = function(customOptions) {


        //==========
        // Logic
        //==========


        //==========
        // Load a module with it's custom options.
        //==========
        function initModule(module, customOptions, coreObject) {
            // Get the previously defined module or the path to load it.
            var moduleName = (require.defined(module)) ? module : config.modulesDir + '/' + module;

            // Initialize the module.
            require([moduleName], function(module) {
                var returnObject = module.init(customOptions, coreObject);

                // Add to the loaded modules if not already present.
                if (settings.modules.indexOf(moduleName) < 0) {
                    settings.modules.push(moduleName);
                    settings.m[moduleName] = returnObject;
                }
            });

            return settings.m[moduleName];
        }


        //==========
        // Logic
        //==========


        //==========
        // Build the core object.
        //==========
        var core = {
            // Properties.
            // Methods.
        }


        //==========
        // Load the defined modules.
        //==========
        $.each(config.modules, function(index, value) {
            initModule(index, value, core);
        });


        //==========
        // Return the core object.
        //==========
        return core;
    }


    //==========
    // Return the initialization object.
    //==========
    return {
        init: init
    }
});

I've been at this for a while now. I'm pretty sure there is a solution, but I can't seem to wrap my head around it. Any guidance is appreciated.

Here is a good chunk of the navigation module code if it helps.

define(['jquery'], function($) {

    //==========
    // Module initialization object.
    //==========
    var init = function(customOptions, core) {
        // Ensure customOptions is an object.
        var customOptions = typeof customOptions !== 'undefined' ? customOptions : {};
        // Get the custom selector or the modules default.
        var selector = typeof customOptions.selector !== 'undefined' ? customOptions.selector : '[' + core.space('data-navigation') + ']';


        //==========
        // Build the jQuery plugin.
        //==========
        $.fn.navigation = function(options) {

            //==========
            // Plugin code.
            //==========

        }


        //==========
        // Initialize the plugin.
        //
        // RUNNING THE PLUGIN FROM HERE DOES WORK, BUT I NEED IT TO WORK FROM THE APP.JS TOO!
        //
        //==========
        $(function() {
            if ($(selector).length > 0) {
                $(selector).navigation(customOptions);
            }
        });


        //==========
        // Return object for core.m.[module]
        //==========
        return {};
    }


    //==========
    // Return the module initialization object.
    //==========
    return {
        init: init
    }
});

In the specific sample above, the solution was to use module = require('moduleName'); instead of require([moduleName], function(module) {} . Here is the new initModule function;

function initModule(moduleName, customOptions) {
    // Do not initiate modules that aren't already loaded.
    if (!require.defined(moduleName)) {
        console.log('Module "' + moduleName + '" is not loaded. Add the module to the app dependency list or use require([moduleName], function(module) { /* Use module here. */ });');
        return false;
    }

    // Require the module.
    module = require(moduleName);

    // Ensure a path is no longer in the name.
    moduleName = moduleName.substr(moduleName.lastIndexOf('/') + 1);

    // Add the modules return to the core object.
    settings.m[moduleName] = module.init(customOptions, core);

    // Add to the loaded modules if not already present.
    if (settings.modules.indexOf(moduleName) < 0) {
        settings.modules.push(moduleName);
    }

    // Return the modules return.
    return settings.m[moduleName];
}

Only problem is this only works if my app.js pulls in the module in it's require() statement. It will still hit the same error if the module is not compiled into the main script file and instead is loaded dynamically. My solution was to just send a message to the console saying to use require([moduleName], function(module) { /* Use module here. */ }); if the module isn't compile into the main script. I'm still seeking a better solution, but it's starting to seem this is inherit in dynamically loading modules.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM