With requirejs is it possible to check if a module is defined without attempting to load it?
Asked Answered
R

2

36

I want to be able to optionally define a module and then use it or not in my code. The particular situation I'm considering is loading mock/stub modules in the debug/test environment but not when I go live. Here is the example:

In the html file the js files would be optionally loaded (pseudo code):

//index.cshtml
...
<script src="/Scripts/lib/require.js"></script>
<script src="/Scripts/app/service_user.js"></script>
<script src="/Scripts/app/real_service.js"></script>
#if DEBUG
<script src="/Scripts/app/mock_service.js"></script>
#endif

In the above both real_service and mock_service must be loaded in the debug version.

Each module would be defined using requirejs, eg:

//mock_service.js
define('mock_service', [], 
    function () {
        ...
    });

//real_service.js
define('real_service', [], 
    function () {
        ...
    });

Then when using the service I'd like to check if the mock_service has been defined:

//service_user.js
define(['require', 'real_service'], 
    function (require, real_service) {
        if (require.isDefined('mock_service')) { // 'isDefined' is what I wish was available
             var mock = require('mock_service');
             mock.init(real_service);
        }

        ...
    });

So my notional 'isDefined' function would just check for a module with the given name (or names?) having been defined. Then in my code, if it is defined I can require it and use it. If not, then that is fine too.

The important thing for me is that no attempt is made to load the optional module. I could try/catch around the require statement but that would cause an attempt to load it from the server and I don't want that.

Another option would be to have a stub define that I always load and so there is always a mock to require which I can then interrogate as to whether it is the real one or not but that seems wasteful too.

Is there any one out there that is deeply in to require.js that has found that they need this functionality and have worked out a strategy for implementation?

Thank you in advance, Rob

Reserpine answered 13/2, 2013 at 10:35 Comment(0)
R
47

Although David Wolf's answer was close to the mark it didn't fully meet my needs.

The problem is that require asynchronously resolves requirements so in the in the example I gave and using David's suggestion require.defined('mock_service') will return false because although it has been specified it has not yet been resolved.

When investigating this I did find another function specified. In the example require.specified('mock_service') will return true but then trying to get a reference using require('mock_service') fails because it hasn't yet been resolved.

That, fortunately, is easily fixed by using the callback version of require. Putting it all together we have:

if (require.specified('mock_service')) {
    require( [ 'mock_service' ], function (mock) {
         mock.init(real_service);
    });
}

@David Wolf - thanks, would not have got there without your help.

Reserpine answered 22/2, 2013 at 16:41 Comment(0)
G
64

I was just looking for this myself, the require global has a "defined" method on it which takes a module name and returns true or false.

// returns true
require.defined("my/awesome/defined/module");

// returns false
require.defined("not/yet/loaded");
Germinal answered 13/2, 2013 at 22:27 Comment(2)
Thx - This almost met my needs and helped me find the right answer which I have now added and marked as the complete solution.Reserpine
just curious, if any alternative in the almond version?Eckhardt
R
47

Although David Wolf's answer was close to the mark it didn't fully meet my needs.

The problem is that require asynchronously resolves requirements so in the in the example I gave and using David's suggestion require.defined('mock_service') will return false because although it has been specified it has not yet been resolved.

When investigating this I did find another function specified. In the example require.specified('mock_service') will return true but then trying to get a reference using require('mock_service') fails because it hasn't yet been resolved.

That, fortunately, is easily fixed by using the callback version of require. Putting it all together we have:

if (require.specified('mock_service')) {
    require( [ 'mock_service' ], function (mock) {
         mock.init(real_service);
    });
}

@David Wolf - thanks, would not have got there without your help.

Reserpine answered 22/2, 2013 at 16:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.