Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The RequireJS order plugin and Dojo 1.7.1

I am upgrading a project from Dojo 1.6.1 using AMD and RequireJS to Dojo 1.7.1 with its new AMD loader. I have to deal with old JavaScript files, not written as AMD modules, and have to load them in the correct order.

Before I used the RequireJS order plugin, but it does not seem to work with Dojo AMD Loader. I can not find anything about it in the loader documentation or the Dojo Build System documentation.

Any thoughts about this? If there is no order plugin, how should I handle plain JavaScript files together with Dojo 1.7? Do I need to handle them separately, or are there functionality for this in the loader or build system?

like image 596
Johan Jonasson Avatar asked Jan 11 '12 09:01

Johan Jonasson


3 Answers

I'm just learning about this myself, but the documentation I found refers to Generic Script Injection

Load your generic scripts as described in the docs, while specifying {async: 0} as a configuration option for require(). This, to my understanding, does load the scripts in the order that you specify in the the second parameter (the array containing the script filenames/paths)

My example:

require({async:0},['test1.js','test2.js','test3.js'],function(){
    //do stuff with reference to loaded scripts

});

My local tests show if I change config to {async: 1} the scripts load in a different order to what I specified. So far I haven't tracked this down in the dojo loader code, but it seems to make sense, and work, and isn't a hack.

like image 68
admataz Avatar answered Oct 24 '22 10:10

admataz


I'd like to propose another approach for such a dependency module as mentioned in the comments above. The problem is that define doesn't accept an async parameter. Using a simple require inside the define function introduces a race condition because the code of the required modules is not executed yet.

Example (WRONG):
oldCode.js

window.foo = function(){};

legacyWrapper.js

define(["require"],function(require){
    require({async:0},["./oldCode"]);
})

code.js

define(["./legacyWrapper"],function(){
    window.foo(); //throws exception, foo has not been loaded yet.
})

(jsFiddle demo)

However, there is a solution to this problem. You need to return a Deferred that gets resolved as soon as all modules are loaded. The following example loads a,b,c,d in order.

define(["require","dojo/Deferred"],function(require,Deferred){
    var def = new Deferred();
    require({async:0},
            ["./moduleA",
             "./moduleB",
             "./moduleC",
             "./moduleD"],
             function(){
        def.resolve();
    });
    return def;
})

To access properties defined in moduleA, you can now use

require(["legacyDeps"],function(legacyDeps){
    legacyDeps.then(function(){
        //It's save to assume that all legacy modules have been loaded here.
    });
});
like image 39
Maximilian Hils Avatar answered Oct 24 '22 10:10

Maximilian Hils


I don't think plugins are generally compatible across AMD loaders. It's not optimal, but you can probably use dojo/text! with an eval. That would inline the content at buildtime.

like image 27
peller Avatar answered Oct 24 '22 09:10

peller