2

I'd like to define A, but A should require B and B require C (for the sake of r.js)

Any of the these two are correct?

define([
    'module'
], function(module) {
    require(['C'], function() {
        require(['B'], function() {

            var A;

            return A;
        });
    });
});


require(['C'], function() {
    require(['B'], function() {
        define([
            'module'
        ], function(module) {
            var A;

            return A;
        });
    });
});

2 Answers 2

5

Neither of your choices are correct.

You first choice attempts to use return to return a value from an asynchronous callback. It is generally not possible, and RequireJS is no different. See this question and its answers for why it is that way.

Your second choice puts a define inside a callback passed to require. This may work in some toy cases but in general this just won't work. (By "toy case" I mean proof-of-concepts where all conditions are under tight control. Such cases do not reflect the realities of real applications.)

Linh Pham's suggestion is really your option here:

define(["module", "B", "C"], function(module){
    var A;

    return A;
});

And if B depends on C and is not a AMD library, put a shim for it. In a comment you objected that you'd have to have "hundreds" of shims if you did this. You have a few options to avoid these shims:

  1. Do not load C with RequireJS. Load it with a script element before RequireJS is loaded on your page.

  2. Design your application to be started with just one module and require that your application be started by loading C before anything else:

    require(['C'], function () {
        require(['main']);
    });
    

    main would be the module that starts your application. The disadvantage of this method is that if you are like me, eventually, you are going to forget to require C before you require main.

Sign up to request clarification or add additional context in comments.

5 Comments

or simply use deps: ["C", "main"] in require.config (note: deps at the same level with shim, path or baseUrl... etc..), I think this should be short and clearer.
@LinhPham deps: ["C"] is asynchronous. There is no point in time by which it is guaranteed that C will be loaded. So if you adapt my last example to use deps:["C"] instead of require(['C'], ... chances are that require(['main']) will execute before C is loaded.
That is very useful info, so in order to use deps: ["C", "main"] I will need to config shim for main module like: shim:{ "main" : ["C"] } right?
Yes, if main happens to be a non-AMD module. I did not state it explicitly in my answer but main should be an AMD module since it is created for the application developed by the OP.
Your second option is what I adapted.
1

just put deps inside define block, like this:

define(["module", "B", "C"], function(module){
    var A;

    return A;
});

If your module B depend on C then you should config it in your require.config like following

shim: {
    "B": ["C"] // shorthand of "B": {deps: ["C"]}
}

3 Comments

That's a good idea. Unfortunately I can't use it. C is like a library module, and I should add hundreds of shim configs if I use this.
you mean that C will be used globally, and all the modules depend on it?
C is not global, but it is required by so many modules so I won't attempt to list them all in shim config.

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.