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?
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.
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)
})
Did you try to override the requirejs.onError like shown here?
It worked for me after setting catchError as true like this:
require.config({catchError:true});
before calling any define() or require() functions.
You can use the requirejs.onError function as :
requirejs.onError = function (err) {
if (err) {
//Reload
}
else {
throw err;
}
};
You can also use err.requireType to catch specific errors like timeouts
Related
Is there a way to add a default behavior in javascript to the throw event.
Like I am trying to add to a file whenever an error is thrown :
Example :
if (tables.length === 0) {
throw new Error("NO_TABLES_RETRIEVED");
}
I want to write to file first and then throw the error. I know I can add a function and just before throwing I can call that function but just to know more is there something like to add a default behavior with throw?
Error is different from Exception in Javascript w.r.t NodeJS. An error is any instance of the Error class. Errors may be constructed and then passed directly to another function or thrown. When you throw an error, it becomes an exception.2 Here's an example of using an error as an exception:
throw new Error('something bad happened');
but you can just as well create an Error without throwing it:
callback(new Error('something bad happened'));
Since you mentioned in the comment that you don't want to require the error handler file in all the files of the app. You can also make use of NodeJS EventEmitter module or use a error handler middleware
I think your best bet is to use a custom throw. I actually always do it, to be able to write
_throw("MyErrorMessage")
So I would do something like that:
//Should use something like dot-env with the path to your errors
require('dotenv').config()
//I'm just gonna fake it to make it work on your machine:
process.env.error_file_path = './myErrors.txt'
//throwLib.js
const util = require('util')
const fs = require('fs')
const writeFile = util.promisify(fs.appendFile)
_throw = (stringError) => {
writeFile(process.env.error_file_path, "Error : " + stringError + "\n").then(err => {
if (err)
console.log(err)
throw new Error(stringError)
}
)
}
//import this in your files.
//myFile.js
//someStuff
_throw('someMessage1')
_throw('someMessage2')
_throw('someMessage3')
You can create your own custom error and do some logic in the constructor.
function MyError(){
//do some logic herer (e.g. write to file)
console.log("some logic");
}
throw new MyError()
If you are using a NodeJS application, you can centrally manage all your thrown errors.
You should also name your errors:
class ApiError extends Error {
constructor (message, code) {
super(message);
this.name = 'ApiError';
this.code = code;
}
}
Similarly use other names for other error types.
For an express application,
app.use(routes);
// place this after your routes in express app. This will catch all your thrown errors.
app.use(function (err, req, res, next) {
console.log(err);
switch (err.name) {
case 'ApiError':
// write to file here
return res.status(err.code || 500).send({error: err.message});
case 'Some other error':
// handle differently
break;
default:
res.status(err.status || 500).render('500', {error: err});
}
});
Note if you are throwing from within a Promise, async/await, this won't catch your error. You will have to catch them centrally some other way, possibly by catching all Unhandled Promise Rejections in your app
process.on('unhandledRejection', (reason) => {
console.log(reason);
// log error in file
});
Similarly, you should also catch all uncaught exceptions centrally
process.on('uncaughtException', (err) => {
console.log(err);
// log error in file
});
Suggestion:
As far as logging errors in file are concerned, it is a great way to do that only if you're parsing your file by some other way, sending your file to logstash etc.
When you're not planning to parse your file programmatically, log your errors in an errordb / error-table. They are much easier to query that way :)
Every function create new Error Object. So how I can get the preivous errors?
For example this is my code:
function main(callback) {
a(function(err) {
if (err) {
callback(new Error('cannot run main function..'));
return
}
})
}
function a(callback) {
b(function(err) {
if (err) {
callback(new Error('cannot run b function'));
return
}
})
}
function b(callback) {
if (1 == 2) callback(new Error('Error in b function'))
}
When I run this, I get only the last error ("cannot run main function') but I want to get all the previous errors. Do you have any best practive for that?
What I am doing is this:
if(err){
err=new Error('cannot run this function.\r' + err.message)
}
I am asking, of you know about any other library or better way for doing that. Something that extend the Error object...
Something like:
err.push(new Error('...'))
There is no "standard" way of doing something like this in Node.js yet. There are various libraries that do what you're describing. The best method I have found is to create a custom error object that extends the default JS Error object, and then define additional methods to it for your purposes. I wrote the x-error library that does just this, you can either use it and extend it (see bottom of README for how to extend it), or just take a look at its code (which is straightforward) and roll your own custom error object implementation.
Note: x-error has a debug method that is similar to what you're looking for.
I'm new to requireJS, and I'm trying to figure out why I can't get normal errors.
I'm using this, right after the requirejs file is loaded, but before any modules are loaded:
requirejs.onError = function (err) {
console.log(err.requireType);
if (err.requireType === 'timeout') {
console.log('modules: ' + err.requireModules);
}
throw err;
};
But I'm still getting the completley vague error:
Error: script error
http://requirejs.org/docs/errors.html#scripterror # http://localhost/wampir/lib/require.js:8
"scripterror"
Is there a way to make this give me the actual error and line number?
I've seen this question but I've tried several answers from there, and they don't change anything...
Remove the "timeout" check. It's keeping you from seeing the modules you're having a problem with unless the problem happens to be a timeout.
requirejs.onError = function (err) {
console.log(err.requireType);
console.log('modules: ' + err.requireModules);
throw err;
};
I am trying to debug emberjs and ember-data application in production server. I am listening on window.onerror so when something breaks I get callback where I can error message, line no and file. But window.onerror behavior is not same across different browsers. Also it doesnot provide stacktrace
So I am using the below function to wrap the ember boundary functions so I can get full stack trace.
function tryCatchWrapper (func, name) {
// Else wrap the function and return it
function wrapped() {
try {
return func.apply(this, arguments);
} catch (e) {
// Report the errors
console.log((name ? name + ": " : "") + e.message);
// Get stacktrace
throw e;
}
}
return wrapped;
};
So what all functions I can wrap using above function so as to get information about all the errors happen in the application without affecting anything?
UPDATE
Added JS Fiddle
Why not use the Ember.onerror event?
Cfr this answer
Example code:
var connection = null;
function onConnect(status) {
im_a_big_error.log('wtf');
// Why it doesn't throw me an error here ??
}
$().ready(function() {
connection = new Strophe.Connection('http://localhost:8080/http-bind');
connection.connect('admin#localhost', 'admin', onConnect);
});
It doesn't throw me an error in my Chrome console.
Do you have an idea to resolve this issue?
Yes, Strophe often catch errors by itself and currently doesn't provide any ability to get connection error information. While error catching is ok, the impossibility of catching errors by yourself is not very good. But you can fix it with the following code:
$().ready(function() {
connection = new Strophe.Connection('http://localhost:8080/http-bind');
connection._hitError = function (reqStatus) {
this.errors++;
Strophe.warn("request errored, status: " + reqStatus + ",
number of errors: " + this.errors);
if (this.errors > 4) this._onDisconnectTimeout();
myErrorHandler(reqStatus, this.errors);
};
connection.connect('admin#localhost', 'admin', onConnect);
});
where myErrorHandler is your custom connection error handler.
Yes, strophe swallows errors. Worse; After an error is thrown, the callback won't return true as it should, and strophe will remove the handler. As soon as an error occurs, the callback will never be called again.
I found the code from the current answer a bit hard to use. Internally, we use the following wrapper for every callback;
function callback(cb) {
// Callback wrapper with
// (1) proper error reporting (Strophe swallows errors)
// (2) always returns true to keep the handler installed
return function() {
try {
cb.apply(this, arguments);
} catch (e){
console.log('ERROR: ' + (e.stack ? e.stack : e));
}
// Return true to keep calling the callback.
return true;
};
}
This wrapper would be used as following in the code of the question;
connection.connect('admin#localhost', 'admin', callback(onConnect));
I've been playing with Strophe for a while now and I had to modify its default error handling routine to fit our needs
Strophe.js - log function - by default contains nothing - I added calls to my server side logging service for level === ERROR and level === FATAL
Strophe.js - run function - the default behavior for error is to remove the handler and to rethrow the error - since I already log the error server side I don't rethrow the error and decided to keep the handler (even if it failed). This behavior could make sense (or not) depending on your own implementation - since I use custom messages and have a rather complicated message processing routine I don't want the client to stop just because a message was not properly formatted when sent so I want to keep the handler, error or not. I replace the throw e line inside the run function with result = true;
Strope.js _hitError - as I mentioned, I don't want the client to ever disconnect so I rewrote the default behavior to never disconnect (no matter how high the error counter)
Hope these thoughts are of help to others - leave a comment if you have questions/want details.
I had a similar problem which I fixed using the approach given by tsds above. However with minimal modification. I created two connect methods one as connect and the other as connect_bak I placed the script
this.connection._hitError=function (reqStatus) {
client.connect_bak();
};
in my connectHandler function as well as the connect function. Such that the function is always binded on connect.