5

I am currently trying to identify the best way to handle different errors within a Durandal application. One scenario I am testing is where the required module does not exist, i.e.

define(['dummy'], function (Dummy) { return {}; });

where dummy does not exist. I have added the following to my main.js file directly below requirejs.config({...}):

requirejs.onError = function (err) {
    console.log('Global error', err);
};

but the error is never logged from here. The 404 error is being shown in the console window from Durandals system.js file and the error message is also logged:

Uncaught Error: Failed to load routed module (viewmodels/features/errorHandling/scriptNotFound/one). Details: Script error for: dummy

It looks like the requirejs.onError function never gets a chance to be called. I would like to be able to log these errors and inform the user that there was a problem etc. Anybody any idea how I would do this?

kryger
  • 12,906
  • 8
  • 44
  • 65
Gary F
  • 360
  • 3
  • 12

5 Answers5

2

I think the best way is to use Durandal's system.error function. Just put something like this somewhere in your appstart:

system.error = function(e) {
  //log the error
  console.debug(e);
  //redirect to a 404 view if you couldn't load module
  if (e.indexOf("Failed to load routed module") > -1) {
    location.href = '#404';
  }
  throw e;
};

On larger projects you may not want to bundle your entire application into a single package so you can load parts of your app incrementally or on demand so as to decrease initial load time in which case you would want to be able to handle load errors.

Brandon Pugh
  • 1,567
  • 1
  • 13
  • 18
2

A common use case for this is to use a CDN-hosted version of a library, but if that fails, switch to loading the file locally:

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
    }
});

//Later
require(['jquery'], function ($) {
    //Do something with $ here
}, function (err) {
    //The errback, error callback
    //The error has a list of modules that failed
    var failedId = err.requireModules && err.requireModules[0];
    if (failedId === 'jquery') {
        //undef is function only on the global requirejs object.
        //Use it to clear internal knowledge of jQuery. Any modules
        //that were dependent on jQuery and in the middle of loading
        //will not be loaded yet, they will wait until a valid jQuery
        //does load.
        requirejs.undef(failedId);

        //Set the path to jQuery to local path
        requirejs.config({
            paths: {
                jquery: 'local/jquery'
            }
        });

        //Try again. Note that the above require callback
        //with the "Do something with $ here" comment will
        //be called if this new attempt to load jQuery succeeds.
        require(['jquery'], function () {});
    } else {
        //Some other error. Maybe show message to the user.
    }
});

http://requirejs.org/docs/api.html#errbacks

Adrian Miranda
  • 315
  • 3
  • 9
0

Brandon is correct. When you use Durandal's router module it calls Durandal's system.acquire which returns a promise that will be called when Require completes loading the module. Require's errback function is provided by Durandal and takes priority over requirejs.onError. When Durandal gets an error it rejects the promise and thus the fail function of Durandal's router is called. All this fail function does is call system.error. Thus when using Durandal, you can capture all the Require module loading errors by providing your own version of system.error.

Spritely
  • 333
  • 2
  • 6
-1

Try making "onError" lowercase like "onerror" (see http://requirejs.org/docs/errors.html#scripterror).

Donald T
  • 10,234
  • 17
  • 63
  • 91
  • Which browser are you testing in? The RequireJS documentation says "onerror" doesn't work in Internet Explorer. – Donald T Mar 02 '15 at 18:03
-1

There's probably no need to handle AMD dependencies load errors, because typically the application would be bundled before going into production.

Error handling as described in http://requirejs.org/docs/api.html#errors deals mostly with jsonp calls to external resources. In addition error handling has some restriction with IE, so that might explain the results that you're seeing.

RainerAtSpirit
  • 3,723
  • 1
  • 17
  • 18
  • Yeah I agree regarding handling the AMD dependencies, I was just using that as an easy way to generate the 404 error. I would just like to be able to handle the error somehow. Maybe I am going about this the wrong way. How would I be able to handle errors with jsonp calls etc? – Gary F Jan 03 '14 at 10:45
  • I think that Durandals system.js uses a jquery deferred to call require and then catches any errors that way. I *don't think* that require uses ajax to get the scripts, I believe that it merely injects the script tag to the head element which is then resolved therefore no ajax errors are thrown (if I am still looking at the scenario of requiring a module which doesn't exist - I haven't looked into jsonp calls etc. yet). I think I may need to understand a bit more of the internals of requirejs and durandal - which I was hoping I wouldn't have to do, I suppose it's a good way to learn though :-) – Gary F Jan 03 '14 at 14:30