We help IT Professionals succeed at work.

Why would I WANT to use try / catch vs a regular IF clause?

Bruce Gust
Bruce Gust asked
on
Here's my code:

module.exports = (req, res, next) => {
	const authHeader = req.get('Authorization');
	if(!authHeader) {
		const error = new Error('Not Even Working');
		error.statusCode = 401;
		throw error;
	} else {
		//const token = authHeader.split(' ')[1];
		let decodedToken;
		try {
			decodedToken = jwt.verify(token, 'secret');
		} catch (err) {
			err.statusCode = 500;
			throw err;
		}
		if(!decodedToken) {
			const error = new Error('Not Authenticated');
			error.statuscode = 401;
			throw error;
		}
		req.userID = decodedToken.userId;
		next();
	}
};

Open in new window


I'm going through some of my back end and forcibly making things go south and I've discovered that I like being able to see things like "Not Even Working," in addition to my status code.

Now, all cards on the table, the above code is coming from a tutorial, so I'm not all that, but I still want to ask this question:

In the first block, I establish an "error" const and I throw my error which has some verbiage that helps me know exactly where things went south.

The next block I've got a try / catch.

Now, when I think "try / catch," I'm thinking this is just a different kind of IF clause, yes? Perhaps the "try" presupposes the fact that we're actually going to fire some kind of function as opposed to just testing the presence of a variable?

But I want to have something even in the context of a "try / catch," where I can specify a "new Error," so I can write some custom verbiage to my console.

So, why am I using "try / catch?" I understand the utility of "throw," because that prevents the code from moving forward.

But why "try / catch? as opposed to a regular IF and can I incorporate some custom verbiage in the midst of that "try / catch?"

Thanks!
Comment
Watch Question

Simple Geek from the '70s
Distinguished Expert 2019
Commented:
can I incorporate some custom verbiage in the midst of that "try / catch?"
try {
 $user =  GET-aduser -identity "notme"
write-host "$user exists"
  }
  catch [System.Management.Automation.CommandNotFoundException]
  {
  write-output 'Get-Aduser Not found'
  }
catch {
write-host "$user doesn't exist or other error"
}

Open in new window

https://community.spiceworks.com/how_to/121063-using-try-catch-powershell-error-handling?login_from=%7C%20google%20%7C%20MVPReg1
leakim971Multitechnician
Distinguished Expert 2019

Commented:
in a true try-catch scenario, you can't use "if" statement instead
try-catch is to handle EXCEPTION which break the normal execution of a program
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
Hey Bruce,

In code, errors can and do happen so they need to be handled. When your application throws an error, it will bubble up the stack until it finds an Exception Handler (a catch block). If it doesn't find one, your whole application will crash and burn because of an Unhandled Exception.

In your first instance you're identifying an error by the false value of the variable. Simply checking the value of a variable won't cause an error, so if you deem that it should be an error, you have to create and throw it yourself. This will bubble up until it finds an exception handler.

In the try/catch block, you can't simply check the value of a variable (decodedToken) because you're calling a function which may throw it's own error. Because that function can throw an error, the variable will never be assigned a value. The error will bubble up the stack until it finds an exception handler - in your case, that's your own catch block. From there, you can do whatever you like. Sometimes, you may just want to log the error and carry on. Other times you may want to set the variable to a default value. In your case, you're handling the error by creating a new error and throwing that. This new error then bubbles up the stack until it finds an Exception Handler.
Most Valuable Expert 2017
Distinguished Expert 2019
Commented:
Definition of throwing an error.

Defensive code is built in such a way that it can recover gracefully from unexpected conditions. Our current code architecture is based on the use of multiple libraries and plugins written by third parties with a published interface or API - in the interests of saving time it makes more sense for us to familiarise ourselves with the parts of the documentation that match our requirements - we don't want to delve into the underlying source code to find what is going on.

In such a scenario how do we deal with errors when calls to functionality can be nested many levels deep?

One strategy is to use the principle of throwing errors. When code encounters a problem it cannot deal with - and there is code up the hierarchy that will be affected by the error there needs to be some way of communicating this. This is where throw / try / catch comes in. Code can throw an error anywhere in the process - and that error will be caught in the first try catch block (which in turn can throw its own error).

In this way notification of serious failure can be eloquently communicated to all parts of the application - between code / libraries written by separate parties. This makes for a much more elegant solution than dealing with a bunch of if / else statements.

If you have complete control over your code you can replace your try / catch with if / else statements. However if you are using other code (which is more the rule than the exception) and that code throw's errors you will need to implement try / catch to catch any errors thrown by that code if you don't want your application to terminate with an exception.
Bruce GustPHP Developer

Author

Commented:
Gentlemen, if I were to try and boil your explanations down into a simple sentence, could that sentence be something like this:

An IF statement is going to look for a value, while an "exception" is going to look for an unsuccessfully completed process (an "exceptional event").

A particular function may operate accurately, but return a NULL value. It's there where I would use an IF statement.

However, if the function itself doesn't fire properly, that qualifies as an "exceptional event" (https://docs.oracle.com/javase/tutorial/essential/exceptions/definition.html) and it's then where I want a "try / catch" so I can see that it's not just a NULL value (undefined), but it's something that went south as a result of flawed syntax.

And with a "try / catch," I've got access to an "exception object" which will have all kinds of valuable info that I can leverage, whereas an IF statement isn't going to give me the same kind of content.

Yes?
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
Hey Bruce,

Basically ... yeah !

You can use an IF statement when you want to check the truthiness of something such as a variable or expression. The value of that expression is generally not an exception. However, according to your own business logic, you may still want say 'hang on a minute - that's not a value I was expecting, so I'm gonna throw an error'. Somewhere along the call stack that thrown error will be caught by an exception handler (a catch block) and dealt with accordingly.

If you think about it, any function you call will pretty much do exactly that, whether you wrote it or not. Say for example I wrote a library containing a lot of functions, and one went something like this;

function Square(number) {
    if (number === 0) {
        throw new Error("You can't square a zero");
    }

    return number * number;
}

Open in new window

You decide to use my library and at some point in your code you call Square(0). That function will now throw an error and that error needs handling. You can wrap it in a try/catch:

try {
    let myVal = Square(0)
catch(err) {
    alert(err);
}

Open in new window

Of you can let it bubble up:

function Func1() {
    try {
        Func2();
    } catch(err) {
        console.log(err)
    }
}

function Func2() {
    return Square(0);
}

Open in new window

Here, you'll see that the call to Square() isn't wrapped in a try/catch, so when the error is thrown it will bubble up the stack until it finds a catch block.

One of the things about throwing exceptions, is the author of the function doesn't know or care how of when the exception will be handled - that's entirely up to the consumer (the author using the function).

As a side note, don't bother using a try/catch unless you're actually going to handle the error at that point. If you're not going to deal with it, let it bubble :)
leakim971Multitechnician
Distinguished Expert 2019

Commented:
the word is : interruption
interruption of the program because of an exceptional event
Bruce GustPHP Developer

Author

Commented:
Thank you!