How can Javascript duplicate the four-part try-catch-else-finally execution model that other languages support?
A clear, brief summary is from the Python 2.5 what's new. In Javascript terms:
// XXX THIS EXAMPLE IS A SYNTAX ERROR
try {
// Protected-block
} catch(e) {
// Handler-block
} else {
// Else-block
} finally {
// Final-block
}
The code in Protected-block is executed. If the code throws an exception, Handler-block is executed; If no exception is thrown, Else-block is executed.
No matter what happened previously, Final-block is executed once the code block is complete and any thrown exceptions handled. Even if there’s an error in Handler-block or Else-block and a new exception is raised, the code in Final-block is still run.
Note that cutting Else-block and pasting at the end of Protected-block is wrong. If an error happens in Else-block, it must not be handled by Handler-block.
I know this is old, but here is a pure syntax solution, which I think is the proper way to go:
try {
// Protected-block
try {
// Else-block
} catch (e) {
// Else-handler-block
}
} catch(e) {
// Handler-block
} finally {
// Final-block
}
The code in Protected-block is executed. If the code throws an error, Handler-block is executed; If no error is thrown, Else-block is executed.
No matter what happened previously, Final-block is executed once the code block is complete and any thrown errors handled. Even if there’s an error in Handler-block or Else-block, the code in Final-block is still run.
If an error is thrown in the Else-block it is not handled by the Handler-block but instead by the Else-handler-block
And if you know that the Else-block will not throw:
try {
// Protected-block
// Else-block
} catch(e) {
// Handler-block
} finally {
// Final-block
}
Moral of the story, don't be afraid to indent ;)
Note: this works only if the Else-handler-block never throws.
Extending the idea of jhs a little, the whole concept could be put inside a function, to provide even more readability:
var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) {
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
finally_code();
}
};
Then we can use it like this (very similar to the python way):
try_catch_else_finally(function() {
// protected block
}, function() {
// handler block
}, function() {
// else block
}, function() {
// final-block
});
I know the question is old and answers has already given but I think that my answer is the simplest to get an "else" in javascripts try-catch-block.
var error = null;
try {
/*Protected-block*/
} catch ( caughtError ) {
error = caughtError; //necessary to make it available in finally-block
} finally {
if ( error ) {
/*Handler-block*/
/*e.g. console.log( 'error: ' + error.message );*/
} else {
/*Else-block*/
}
/*Final-block*/
}
Javascript does not have the syntax to support the no-exception scenario. The best workaround is nested try statements, similar to the "legacy" technique from PEP 341
// A pretty-good try/catch/else/finally implementation.
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
this_always_runs();
}
Besides readability, the only problem is the success variable. If protected_code sets window.success = false, this will not work. A less readable but safer way uses a function namespace:
// A try/catch/else/finally implementation without changing variable bindings.
try {
(function() {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
})();
} finally {
this_always_runs();
}
Here's another solution if the problem is the common one of not wanting the error callback to be called if there is an uncaught error thrown by the first callback. ... i.e. conceptually you want ...
try {
//do block
cb(null, result);
} catch(err) {
// err report
cb(err)
}
But an error in the success cb causes the problem of cb getting called a second time. So instead I've started using
try {
//do block
try {
cb(null, result);
} catch(err) {
// report uncaught error
}
} catch(err) {
// err report
cb(err)
}
which is a variant on #cbarrick's solution.
Related
Throwing error to upper level in an async function
This
async create(body: NewDevice, firstTry = true): Promise<RepresentationalDevice> {
try {
return await this.dataAccess.getAccessToken()
} catch (error) {
throw error
}
}
VS this
async create(body: NewDevice, firstTry = true): Promise<RepresentationalDevice> {
return await this.dataAccess.getAccessToken()
}
I mean at the end on the upper level I must catch the error anyway and there is no modifications at all on the catch
Are these two approaches identical? Can I use the second approach without error handling issues?
This has nothing to do with async functions. Catching an error just to rethrow it is the same as not catching it in the first place. I.e.
try {
foo();
} catch(e) {
throw e;
}
and
foo();
are basically equivalent, except that the stack trace might be different (since in the first case the error is thrown at a different location).
I have some issue with calling function of null variable in 'then' callback of Q.promise.
The first call (without Q using) will show an error, but while the second (wuth Q using) doesn't.
Small example:
var Q = require('q');
var nul = null;
var exp;
(function (exp) {
var A = (function () {
function A() {
};
A.prototype.foo = function () {
var d = Q.defer();
d.resolve('Hello, world');
return d.promise;
};
A.prototype.bar = function (i) {
switch (i) {
case 0:
/**
* That's all ok, "TypeError: Cannot read property 'qqq' of null"
*/
console.log(nul);
nul.qqq();
console.log('ok');
break;
case 1:
/**
* it's not ok, I see only result of "console.log(nul)", line 29
*/
this.foo().then(function () {
console.log(nul);
nul.qqq();
console.log('ok');
});
break;
};
};
return A;
})();
exp.A = A;
}) (exp || (exp = {}));
exp.a = new exp.A();
// You should run functions SEPARATELY!!!
exp.a.bar(0); // in that case: that's all ok, "TypeError: Cannot read property 'qqq' of null"
exp.a.bar(1); // int that case: it's not ok, I see only result of "console.log(nul)", line 29
I don't have any idea how to solve it
The reason why you're not seeing the second error on the console is because Q catches all errors and lets you handle them separately.
You can handle an error in then() by chaining with a catch() function, in your example this can be done this way:
this.foo().then(function () {
console.log(nul);
nul.qqq();
console.log('ok');
}).catch(function(error) {
// do something with error
console.log(error);
});
You can get this behavior also by using a try/catch block inside then() like this:
this.foo().then(function () {
try {
console.log(nul);
nul.qqq();
console.log('ok');
} catch (e) {
console.log(e);
}
});
Old answer
Here are a few options for catching errors in JS/node.js:
Try/Catch blocks
These work like in their Java/C# equivalent, wrap each of the calls you make with a try block and catch an error, handling it in the catch block
try {
exp.a.bar(0);
} catch(e) {
console.log(e);
}
You can also add finally blocks, check the type of an exception/error and so on, you can read more about it on the MDN page
Node.js uncaughtException handler
In node, you can catch all uncaught errors, which will stop your program, by binding a callback to the uncaughtException event like this:
process.on('uncaughtException', function (e) {
console.log('Error: ' + e);
});
This isn't always the best thing to do in a program, but if you really don't want to stop the execution, this is an option.
Finally, I recommend giving a look to this official article for best practices about handling errors in node.js
I have an Ajax object which is used in some other objects to load 'Json' files.
I need to catch the 404 'Not found' thrown exception in the initializer object, but I couldn't do this it always gives me:
Uncaught Exception : *********
here a piece of code:
_ajax_params.xmlhttp.onreadystatechange = function() {
if (_ajax_params.xmlhttp.readyState==4 && _ajax_params.xmlhttp.status==200) {
_ajax_params.response = _ajax_params.xmlhttp.responseText;
if (typeof afterClosure == 'function') {
afterClosure(_ajax_params.response);
}
COMMON.always(_ajax_params.response);
} else if (_ajax_params.xmlhttp.status== 404) {
throw 'File not found';
}
};
In the initializer object:
try {
Base.include.json(url, 1);
} catch (e) {
console.error(e);
Base.include.json(url,2);
}
I tried to re-throw exception, but I got the same.
You may have defined the callback within a try..catch block, but the function is executed outside of said block (ie. when the event is fired). This means that exceptions that happen in the callback will not be caught by the outside block.
Here is a demonstration of the difference in action.
Consider calling Base.include.json(url,2) in place of throw 'File not found';
Additionally, you shouldn't really check status unless you already know that readyState is 4, but that's a minor thing.
if(a.value==1 && b.value==2)
{
try{callFunc() }catch(e) {}
}
frm.submit();
Inside function callFunc(), what do I have to write so that execution completely stops?
It should not execute frm.submit();
function callFunc()
{
//stop execution here -- ensure it won't execute fm.submit()
}
Better one is
function Abort()
{
throw new Error('This is not an error. This is just to abort javascript');
}
than from any where call this
try
{
for(var i=0;i<10;i++)
{
if(i==5)Abort();
}
} catch(e){}
For you
function callFunc()
{
//stop execution here
Abort();
}
//code from where you are going to call
try
{
if(a.value==1 && b.value==2)
{
callFunc()
}
frm.submit();
}
catch(e) {}
As you've discovered, aborting JavaScript almost always involves exceptions. If you truly can't change the wrapper, then you might have to resort to something a bit more extreme. One (evil) way to kill the script is to convince the browser that it's taking too long, by running an infinite loop:
function callFunc()
{
//stop execution here
var n = 1;
while (n) {
n += 1;
}
}
Modern browsers will let the user kill the script after a while. Granted, it will make your site seem broken, but that should give you the leverage you need to get a better API in place.
If the busy-loop is too extreme, you could replace the simple addition with a plugin-based sleep, or perhaps a synchronous network request that takes an extremely long time, wrapped in its own try/catch safety net.
I understand what you are trying to do. You don't want to kill the Javascript interpreter, you just want to prevent the form submission from proceeding.
HTML
<form id="myForm">
…
</form>
Javascript
// Setup…
var frm = document.getElementById('myForm'),
a = { value: 1 },
b = { value: 2 };
// Can change this code
var callFunc = function() {
// Throwing will do nothing here, since
// exceptions are being caught in a try/catch
// Instead, let's overwrite the submit handler with one that
// will cancel the form submission, then restore the old handler
var oldSubmitHandler = frm.submit;
var killHandler = function(e) {
// Prevents the submission
e.preventDefault();
// Restores the old handler
frm.submit = oldSubmitHandler;
};
frm.submit = killHandler;
};
// Can't change any of this code
if(a.value==1 && b.value==2)
{
try { callFunc() } catch(e) { }
}
// Want to stop this from happening
frm.submit();
See it in action: http://jsfiddle.net/3A7xC/
Better way is this:
if(a.value==1 && b.value==2)
{
try{
callFunc();
frm.submit();
}
catch(e) {
// stop execution
}
}
If an exception is thrown in function callFunc, the frm.submit(); line would not be executed. Instead, it will skip to the catch clause
Lots of answers, one more for fun.
You can put the code in a function, have the try block throw an error, then return from the catch clause:
function foo() {
var a = {value:1};
var b = {value:2};
if(a.value==1 && b.value==2) {
try {
callFunc();
} catch(e) {
alert(e.message);
return;
}
}
alert('error didn\'t stop me!');
}
function callFunc() {
throw new Error('This is an error.');
}
Otherwise you can set a flag in the catch block and test for it immediately afterward before going any further. Or take one of the other answer's options.
So the inside of the callFunc is the only thing you can change?
How about this:
callFunc(){
frm.submit(function() {
alert('this should not submit');
return false;
});
}
To kill the execution of a JS script use:
system.stop()
You can abort javascript execution using throw:
if(a.value==1 && b.value==2){
try{callFunc() }catch(e) {}
}
frm.submit();
function callFunc() {
throw "stop execution";
}
How can Javascript duplicate the four-part try-catch-else-finally execution model that other languages support?
A clear, brief summary is from the Python 2.5 what's new. In Javascript terms:
// XXX THIS EXAMPLE IS A SYNTAX ERROR
try {
// Protected-block
} catch(e) {
// Handler-block
} else {
// Else-block
} finally {
// Final-block
}
The code in Protected-block is executed. If the code throws an exception, Handler-block is executed; If no exception is thrown, Else-block is executed.
No matter what happened previously, Final-block is executed once the code block is complete and any thrown exceptions handled. Even if there’s an error in Handler-block or Else-block and a new exception is raised, the code in Final-block is still run.
Note that cutting Else-block and pasting at the end of Protected-block is wrong. If an error happens in Else-block, it must not be handled by Handler-block.
I know this is old, but here is a pure syntax solution, which I think is the proper way to go:
try {
// Protected-block
try {
// Else-block
} catch (e) {
// Else-handler-block
}
} catch(e) {
// Handler-block
} finally {
// Final-block
}
The code in Protected-block is executed. If the code throws an error, Handler-block is executed; If no error is thrown, Else-block is executed.
No matter what happened previously, Final-block is executed once the code block is complete and any thrown errors handled. Even if there’s an error in Handler-block or Else-block, the code in Final-block is still run.
If an error is thrown in the Else-block it is not handled by the Handler-block but instead by the Else-handler-block
And if you know that the Else-block will not throw:
try {
// Protected-block
// Else-block
} catch(e) {
// Handler-block
} finally {
// Final-block
}
Moral of the story, don't be afraid to indent ;)
Note: this works only if the Else-handler-block never throws.
Extending the idea of jhs a little, the whole concept could be put inside a function, to provide even more readability:
var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) {
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
finally_code();
}
};
Then we can use it like this (very similar to the python way):
try_catch_else_finally(function() {
// protected block
}, function() {
// handler block
}, function() {
// else block
}, function() {
// final-block
});
I know the question is old and answers has already given but I think that my answer is the simplest to get an "else" in javascripts try-catch-block.
var error = null;
try {
/*Protected-block*/
} catch ( caughtError ) {
error = caughtError; //necessary to make it available in finally-block
} finally {
if ( error ) {
/*Handler-block*/
/*e.g. console.log( 'error: ' + error.message );*/
} else {
/*Else-block*/
}
/*Final-block*/
}
Javascript does not have the syntax to support the no-exception scenario. The best workaround is nested try statements, similar to the "legacy" technique from PEP 341
// A pretty-good try/catch/else/finally implementation.
try {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
} finally {
this_always_runs();
}
Besides readability, the only problem is the success variable. If protected_code sets window.success = false, this will not work. A less readable but safer way uses a function namespace:
// A try/catch/else/finally implementation without changing variable bindings.
try {
(function() {
var success = true;
try {
protected_code();
} catch(e) {
success = false;
handler_code({"exception_was": e});
}
if(success) {
else_code();
}
})();
} finally {
this_always_runs();
}
Here's another solution if the problem is the common one of not wanting the error callback to be called if there is an uncaught error thrown by the first callback. ... i.e. conceptually you want ...
try {
//do block
cb(null, result);
} catch(err) {
// err report
cb(err)
}
But an error in the success cb causes the problem of cb getting called a second time. So instead I've started using
try {
//do block
try {
cb(null, result);
} catch(err) {
// report uncaught error
}
} catch(err) {
// err report
cb(err)
}
which is a variant on #cbarrick's solution.