Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching module loading errors and processing them

I am trying to load some content using require.js. If the content doesn't exist I'd like to catch the error and notify the user.

In firebug I can see two errors:

"NetworkError: 404 Not Found

...and then a few seconds later:

var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#
Load timeout for modules: modules/messages/messages 
http://requirejs.org/docs/errors.html#timeout

My code resembles:

require([path], function(content){
  //need to catch errors as this will not be called;
});

How would one bind to requirejs events? Any idea?

like image 394
Chin Avatar asked Jan 27 '12 11:01

Chin


2 Answers

It is also possible to use errbacks to have customized error handling appropriate to the specific use of require. Errbacks are documented here http://requirejs.org/docs/api.html#errbacks. Basically, you can add to require a function to be called if the load fails. It comes right after the function to be called if the load is successful.

Chin's case could be handled as:

require([path], function(content){
  //need to catch errors as this will not be called;
}, function (err) {
  //display error to user
});

Here's an example that tries loading from multiple places:

require([mode_path], onload, function (err) {

    if (mode_path.indexOf("/") !== -1)
        // It is an actual path so don't try any further loading
        throw new Error("can't load mode " + mode_path);

    var path = "./modes/" + mode_path + "/" + mode_path;
    require([path], onload,
            function (err) {
        require([path + "_mode"], onload);
    });
});

In this example onload would be the function called once the required code loads, and mode_path is a string identifying the mode. What you see there is code attempting to load a mode module for an editor from 3 different locations. If mode_path is foo, it will try to load foo, then ./modes/foo/foo and then ./modes/foo/foo_mode.

The example at requirejs.org shows how one might handle a case where they want to try multiple locations for a resource they want to make available with a well-known identifier. Presumably the entire code-base in that example requires jQuery by requiring "jquery". Whatever location jQuery happens to be located at, it becomes available to the whole code-base as "jquery".

My example does not care about making the mode known to the entire code-base through a well-known identifier because in this specific case there's no good reason to do so. The onload function stores the module it gets into a variable and the rest of the code base gets it by calling a getMode() method.

like image 74
Louis Avatar answered Oct 22 '22 17:10

Louis


set the requirejs onError function:

requirejs.onError = function (err) {
    if (err.requireType === 'timeout') {
        // tell user
        alert("error: "+err);
    } else {
        throw err;
    }
};

If you want to setup an event you could bind to and trigger a global object. Such as:

$("body").bind("moduleFail",function(){
    alert("Handling Event")
});
requirejs.onError = function (err) {
    if (err.requireType === 'timeout') {
        $("body").trigger({type:"moduleFail",err:err})
    } else {
        throw err;
    }
};
require(["foo"],function(foo){
    alert("loaded foo" + foo)
})
like image 19
Shanimal Avatar answered Oct 22 '22 17:10

Shanimal