I have a number of functions which either return something or throw an error. In a main function, I call each of these, and would like to return the value returned by each function, or go on to the second function if the first functions throws an error.
So basically what I currently have is:
function testAll() {
try { return func1(); } catch(e) {}
try { return func2(); } catch(e) {} // If func1 throws error, try func2
try { return func3(); } catch(e) {} // If func2 throws error, try func3
}
But actually I'd like to only try to return it (i.e. if it doesn't throw an error). I do not need the catch block. However, code like try {} fails because it is missing an (unused) catch {} block.
I put an example on jsFiddle.
So, is there any way to have those catch blocks removed whilst achieving the same effect?
A try without a catch clause sends its error to the next higher catch, or the window, if there is no catch defined within that try.
If you do not have a catch, a try expression requires a finally clause.
try {
// whatever;
} finally {
// always runs
}
It's possible to have an empty catch block, without an error variable, starting with ES2019. This is called optional catch binding and was implemented in V8 v6.6, released in June 2018. The feature has been available since Node 10, Chrome 66, Firefox 58, Opera 53 and Safari 11.1.
The syntax is shown below:
try {
throw new Error("This won't show anything");
} catch { };
You still need a catch block, but it can be empty and you don't need to pass any variable. If you don't want a catch block at all, you can use the try/finally, but note that it won't swallow errors as an empty catch does.
try {
throw new Error("This WILL get logged");
} finally {
console.log("This syntax does not swallow errors");
}
Nope, catch (or finally) is try's friend and always there as part of try/catch.
However, it is perfectly valid to have them empty, like in your example.
In the comments in your example code (If func1 throws error, try func2), it would seem that what you really want to do is call the next function inside of the catch block of the previous.
I wouldn't recommend try-finally without the catch, because if both the try block and finally block throw errors, the error thrown in the finally clause gets bubbled up and the try block's error is ignored, in my own test:
try {
console.log('about to error, guys!');
throw new Error('eat me!');
} finally {
console.log ('finally, who cares');
throw new Error('finally error');
}
Result:
> about to error, guys!
> finally, who cares
> .../error.js:9
> throw new Error('finally error');
> ^
>
> Error: finally error
No, it is not possible to have try block without catch (or finally). As a workaround, I believe you might want to define a helper function such as this:
function tryIt(fn, ...args) {
try {
return fn(...args);
} catch {}
}
and use it like:
tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
I've decide to look at the problem presented from a different angle.
I've been able to determine a way to to allow closely for the code pattern requested while in part addressing the un-handled error object listed by another commenter.
code can be seen # http://jsfiddle.net/Abyssoft/RC7Nw/4/
try:catch is placed within a for loop allowing graceful fall through. while being able to iterate through all the functions needed. when explicit error handling is needed additional function array is used. in the even of error and functional array with error handlers element is not a function, error is dumped to console.
Per requirements of stackoverflow here is the code inline [edited to make JSLint compliant (remove leading spaces to confirm), improve readability]
function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }
// ctr = Code to Run <array>, values = values <array>,
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
"use strict";
var cb; // cb = code block counter
for (cb in ctr) {
if (ctr.hasOwnProperty(cb)) {
try {
return ctr[cb](values[cb]);
} catch (e) {
if (typeof eh[cb] === "function") {
eh[cb](e);
} else {
//error intentionally/accidentially ignored
console.log(e);
}
}
}
}
return false;
}
window.alert(testAll([func1, func2, func3], [], []));
If you only want functions 2 and 3 to fire if an error occurs why are you not putting them in the catch block?
function testAll() {
try {
return func1();
} catch(e) {
try {
return func2();
} catch(e) {
try {
return func3();
} catch(e) {
// LOG EVERYTHING FAILED
}
}
}
}
...is there any way to have those catch blocks removed whilst achieving the same effect? As it would seem, no; Javascript requires a try block be followed by either a catch or a finally block.
Having said that, there is a way to use those catch blocks to achieve the effect you want.
// If func1 throws error, try func2 The if throws error condition, is what the catch block is for.
Why remove them when their use is exactly what you are after?
try { return func1(); }
catch {
// if func1 throws error
try { return func2(); }
catch {
// if func2 throws error
try { return func3(); }
catch {
// if func3 throws error
}
}
}
I completely understand why you might not need a catch block, and would find it cleaner to be able to omit it entirely. But I don't think this is one of those situations.
They go together in every language that I know that has them (JavaScript, Java, C#, C++). Don't do it.
Since ES2019 you can easily use try {} without catch {}:
try {
parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}
For more info please reffer to Michael Ficcara's proposal
try & catch are like 2 side of one coin. so not possible without try.
No. You have to keep them.
This actually makes sense since errors shouldn't be silently ignored at all.
Related
I'm still learning the language, and I'm very curious to know what is the proper way to ensure that either all functions will execute or none when one action requires series of functions to be executed. For example I might have an HTML button that calls some apply() function:
function apply() {
try {
// Check arguments, choose what exactly to do next through some IFs etc...
}
anotherFunction();
}
function anotherFunction() {
try {
// Request data from DB, process data received, update object variables, etc...
}
yetAnotherFunction();
}
function yetAnotherFunction() {
try {
// Update HTML
}
oneMoreFunction();
}
function oneMoreFunction() {
try {
// Update graph
}
}
So the problem here is that if any of the functions in the flow throws an error the rest functions won't do what they should, hence the entire Apply process will be interrupted with some changes applied (let's say HTML is getting updated) but the rest (the graph) is not. I'm curious to know what is the best practice to prevent this behaviour? Yes I'm trying my best to use try {} and check arguments for errors etc, but it looks like I can't foresee everything, I just need some way to tell the code "ensure you can execute all of the functions, in case of any errors, just don't do anything at all". Please advise what can be done here?
You're taking the right path when thinking about try/catch blocks, but notice I used a 'catch' as well. Usually (maybe that is even enforced, I can't remember) you need the catch blocks along with the try.
So your functions could look something like this:
function async myFirstTryCatch() {
try {
// Make your request in the try block
await requestCall();
} catch(error){
// Hey, my http call returned an error
// Deal with the error here. Maybe show a toast, validate a form
// Anything you need to not break the code and have good UX
console.log(error)
}
}
In that same line of thought, you could have each function handle their own try/catch or maybe control that in your apply function, in case some of the chain must continue/stop depending each other.
function apply() {
try {
firstCall();
functionThatRequiresFirstCalltoSucceed();
} catch (error){
//Will catch if either firstCall or functionThatRequiresFirstCalltoSucceed fail
console.log(error)
}
functionThatIndependsFromTheResultAbove();
}
I hope this will help you build your thoughts about error handling in JS :)
IMPORTANT NOTE
If your code enters the catch block, it will consider that the error has been dealt with and will not propagate! Here's an example
function functionThatThrowsError(){
try{
throw new Error('Example Error!');
} catch (error) {
// Error has been dealt with
console.log(error) // Returns "Example Error"
// throw error; <--- Throw the error in the catch block if you need t to propagate
}
}
function wontCatchError() {
try {
functionThatThrowsError();
} catch (error) {
// THE CODE WILL NOT ENTER THE CATCH BLOCK
// SINCE THE ERROR WAS CAUGHT IN THE FUNCTION ITSELF.
// If you need to catch here as well, make sure to throw the error
// in the catch block of the 'functionThatThrowsError'
console.log(error)
}
}
The following script enables you to run a piece of javascript code. Errors are being catched by the try / catch block.
try {
var result = eval(script);
} catch (e) {
// do something meaningful
}
However, if the variable script contains for instance an AJAX call, and this ajax call throws an exception (e.g. in the success function), this exception will NOT be catched by this try / catch block...
// execute an AJAX request
var script = '$.ajax(url:"/somewhere", success: function(){throw new MyException('testexception')})';
try {
var result = eval(script);
} catch (e) {
// will not be triggered...
}
Question: how can I catch the exception thrown within the ajax request?
I hope you are aware of the dangers of using eval, and if not there are plenty of good articles out there that explain why it is not a good idea.
That being said, the issue is that the success callback is being called after the catch block. You'll need to either add the try/catch block within the success callback, or you'll need to handle the error from a more global perspective. One idea I can think of to do this is using the window.onerror event. I have an example below that shows something similar to your problem, and one that shows you can catch errors thrown in eval.
(function() {
'use strict';
window.addEventListener('error', e => console.log(`window.onerror: ${e.message}`));
let script = `setTimeout(function() {
throw new Error('Whoops!');
}, 0);`;
eval(script);
script = `throw new Error('Whoops!');`;
try {
eval(script);
} catch (e) {
console.log(e.message);
}
})();
Try catch is used to catch errors and report to user. all said and fine. But where exactly one has to put the try-catch. Or What exactly has to go inside try catch on a usual basis.
Most importantly, is it absolutely a good coding practice to have a try catch block?
I think it is good practce to use a try catch if it will handle errors and prevent the program from crashing.
Taken from W3 Schools:
The try statement lets you test a block of code for errors.
The catch statement lets you handle the error.
The throw statement lets you create custom errors.
The finally statement lets you execute
code, after try and catch, regardless of the result.
An example:
fuction foo()
{
try
{
// Block of code to try
}
catch(e)
{
// Block of code to handle errors
document.getElementById("demo").innerHTML = e.message;
}
finally
{
// Block of code to be executed regardless of the try / catch result
}
}
Here is soem more documentation at W3 Schools: http://www.w3schools.com/js/js_errors.asp
Yes, it absolutely good practice to use try-catch blocks. Here's a rather simplistic (but contrived) demonstration.
function safeParseJSON(json) {
try {
return JSON.parse(json);
} catch(exception) {
// could not parse this JSON
console.error(exception);
} finally {
return null;
}
}
Parsing JSON is the most common scenario I have encountered for using the try-catch construct, hence the example.
However, the usual try-catch mechanism doesn't work when the function is asynchronous. It's essential to understand this if you are ever using a server side Javascript platform.
The standard pattern for async event handling is as follows.
db.connect(options, function connected(err, client) {
if(err) throw err;
client.query(...);
});
Because that callback function is run somewhere else (presumably when the database connects) we can't wrap it with a try-catch block. Instead, most async method calls will pass the error as the first argument to the callback.
This way we can handle the error as and when it happens. If there is no error, null will be passed as the first argument, so that it can be ignored.
A number of implementations of promises try to recreate this mechanism, but in an asynchronous way.
Here's an example with Q:
db.connect(options)
.then(function(client) {
client.query(...);
})
.catch(function (error) {
throw error;
})
.fin(function() {
// finally
db.close();
});
You can also use Q on the client side, if you are working with asynchronous functions.
I've got the following code:
try {
...
try {
// This is *never* called
alert('TRY');
} catch (e) {
// But this *is* called
alert('CATCH');
}
} catch (e2) {
...
}
The problem is, the alert from the inner catch block is executed but not the one from the inner try.
Is this possible at all per specification or does anyone have an idea what is happening here ?
Can an exception from e.g. asynchronous code run into the context of another catch block ?
Note this is real code I put in there, no omissions in the inner try / catch !
Some asynchronous code may be run before entering the block.
This is from code taken from a web app running in WebKit / QtWebKit from PyQt 4.9.0 and Qt 4.8.0.
Ok, so here some more code before the inner try/catch (where the first ellipsis is):
DoSomething(function () {
var updatePromises = [];
var p;
for (...) {
p = new Promise();
updatePromises.push(p);
// Run asynchronous code to fulfill promise.
// Calls are chained using an array and a "setTimeout()" mechanism.
tasks.chain(function (promise) { ... }, this, p);
}
(function () {
...
}).future().apply(this, updatePromises);
}.bind(this));
The ES5 specification says the following (emphasis added):
The try statement encloses a block of code in which an exceptional
condition can occur, such as a runtime error or a throw statement. The
catch clause provides the exception-handling code.
...
The production TryStatement : try Block Catch is evaluated as follows:
Let B be the result of evaluating Block.
If B.type is not throw, return B.
Return the result of evaluating Catch with parameter B.
My understanding of that is that, according to the spec, there is no way a catch block can be executed without first evaluating the try block.
I think the answer is no, based on the mozilla reference. I recommend you log each time a block is entered and exited, and see if there is any weird stuff going on that you missed. Maybe use debugger; too.
Or try this perhaps:
var foo = false;
try {
try {
foo = true;
throw true;
} catch (e) {
if(foo) {
alert('CATCH');
} else {
alert('HUH?');
}
}
} catch (e2) {
alert('CATCH2');
}
When I try the following in the chrome console, i get 'undefined' as the value of 'e':
try{
var test=somethingInvalid();
}
catch(e){
console.log(e);
}
How do I access the details of e?
What properties does it have?
Thanks.
Doh. Doing console.log('E is: '+e) seams to work. Sorry!
Well, it will return undefined, because the last line console.log doesn't return a value.
try{
false = true;
}
catch(e){
console.log(e);
}
but with the above you will also see an object > Reference Error followed by the next line of undefined
According to MDN, it is the value on the throw statement.
https://developer.mozilla.org/en/JavaScript/Reference/Statements/try...catch
The exception identifier
When an exception is thrown in the try block, exception_var (e.g.
the e in catch (e)) holds the value specified by the throw statement.
You can use this identifier to get information about the exception
that was thrown.
This identifier is local to the catch clause. That is, it is created
when the catch clause is entered, and after the catch clause finishes
executing, the identifier is no longer available.
As far as I can see, Chrome does output the details of 'e'. I just did this:
var err;
try { /* what you did */ }
catch (e) { err = e; }
upon which Chrome shows you the details of 'e'.
In this case, you can perform calls to see the contents of the following:
err.name
err.arguments
err.type
err.stack
Good luck!
although all the answers provided were very helpful, what we were infact looking for was:
try{
var test=somethingThatDoesntExist();
}
catch(e){
console.log(e.message);
}
e.message is the variable we want to log, as it (to the best of our knowledge) contains a string representation of the error that was caught.
thanks!
I have a custom assert() function that pulls a stack trace of functions (in all modern browsers, except IE):
if (!condition) {
try {
throw Error();
} catch (e) {
// Browsers Firefox, Chrome, Opera provide additional stack property;
// Check if it does not exist (IE);
stackTrace = (!e.stack) ? "No stack available" : e.stack;
self.reportError(errorType, stackTrace, message);
}
}
Obviously, there is a lot more going on than what I'm showing, but the idea is there.