23

I'd like to define a module which computes a new dependancy, fetches it and then returns the result. Like so:

define(['defaults', 'get_config_name'], function(defaults, get_config_name) {
    var name = get_config_name();
    var config;
    require.synchronous([configs / '+name'], function(a) {
        config = defaults.extend(a);
    });
    return config;
});

Is there a way to do this or a better way to attack this problem?

1
  • 2
    I guess for this to work require.js would have to append a script tag to the body then jump into a while loop to suspend execution while it checks for the script to loading. Commented Nov 5, 2012 at 3:21

2 Answers 2

19
  • You may try to use synchronous RequireJS call require('configs/'+get_config_name()), but it will load a module synchronously only if it is already loaded, otherwise it will throw an exception. Loading module/JavaScript file synchronously is technically impossible. UPD: It's possible (see Henrique's answer) but highly unrecommended. It blocks JavaScript execution that causes to freezing of the entire page. So, RequireJS doesn't support it.

  • From your use case it seems that you don't need synchronous RequireJS, you need to return result asynchronously. AMD pattern allows to define dependencies and load them asynchronously, but module's factory function must return result synchronously. The solution may be in using loader plugin (details here and here):

    // config_loader.js
    define(['defaults', 'get_config_name'], function(defaults, get_config_name) {
        return {
            load: function (resourceId, require, load) {
                var config_name = 'configs/' + get_config_name();
                require([config_name], function(config) {
                    load(defaults.extend(config));
                })
            }
        }
    });
    
    // application.js
    define(['config_loader!'], function(config) {
        // code using config
    });
    
  • If get_config_name() contains simple logic and doesn't depend on another modules, the better and simpler is calculating on the fly paths configuration option, or in case your config depends on context - map configuration option.

    function get_config_name() {
        // do something
    }
    require.config({
        paths: {
            'config': 'configs/' + get_config_name()
        }
    });
    require(['application', 'defaults', 'config'], function(application, defaults, config) {
        config = defaults.extend(config);
        application.start(config);
    });
    
Sign up to request clarification or add additional context in comments.

Comments

15

Loading JavaScript synchronously is NOT technically impossible.

function loadJS(file){  
   var js = $.ajax({ type: "GET", url: file, async: false }).responseText; //No need to append  
}

console.log('Test is loading...');
loadJS('test.js');
console.log('Test was loaded:', window.loadedModule); //loadedModule come from test.js

5 Comments

Yes @Henrique, you are right. I discovered this technique after I have published the answer. I updated the answer. Thank you! By the way: I think you were downvoted because you published it not as a comment to the answer but as a separate answer.
No problem. I published as an answer because I don't have "reputation" to post comments.
Just fetching the file and assigning it to a variable will run it? What am I missing?
synchronous XMLHttpRequest and eval is possible at least on chrome and firefox. note that if using it locally you'll probably need --allow-file-access-from-file
Now, 2019, this is still working... you can easily reproduce it. I haven't found anything on specs, but when you fetch an javascript file with content-type: application/javascript it will RUN the js code. To test: Open chrome dev tools and register my loadJS function and run loadJS('https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js') You will see that underscore _ will be available now (you should test for its non presence before)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.