Hi everyone, and welcome to another exciting edition of Boring JavaScript!
Today, we tackle the Try/Catch statement – with a little help from our friends, ‘throw’ and ‘finally’.
Catch Me If You Can
Your application is running along just fine, when suddenly it stops. That’s right. Just stops working.
Thinking ahead, you’ve coded your app to log any messages, as such you go to your logs and find out that a JSON file you expected to be there wasn’t, and your application threw an error because it couldn’t find it. Simple to fix – you just add the file into the system. But that got you thinking – wouldn’t it have been better if you displayed some sort of error message inside your application so that the user will have instant knowledge of what went wrong? And they could fix it right then and there instead of having to go through one-hundred gigs of logs?
Yes, that would be better. Enter ‘try/catch’.
If at first you don’t succeed, Try, Try, again.
Try/Catch with JavaScript is a method of capturing exceptions in JavaScript and then determining courses of action to take if an error occurs.
In our example, we will be reading from a JSON resource, process that resource, display it, then close out the resource. Let’s take a look at what a Try/Catch series of blocks will look like:
const resource = "./mydata.json";
let data, handle;
try {
({ data, handle } = readResource(resource));
data = processResource(data);
displayResource(data);
closeResource(handle);
} catch(err) {
displayError(err, data);
closeResource(handle);
}
There are two blocks here – the ‘try’ block and the ‘catch’ block;
The Try Block
The Try block will execute all the code within the block as you would expect any normal JavaScript app to do. In our case, there will be four functions – readResource, processResource, displayResource, and closeResource. So far, nothing out of the ordinary.
But if an exception occurs within the block – say, for example, readResource throws and exception because our resource “./mydata.json” doesn’t exist – then the execution of the code will be passed to the ‘Catch’ block, with the Error event passed as an argument.
try {
({ data, handle }) = readResource(resource); // assume an error occurred here!!
data = processResource(data); // this line and the next two will not get executed...
displayResource(data);
closeResource(handle);
} catch(err) { // ...and execution will get passed to here.
And that’s the secret with the Try block: With any other code, an thrown exception would halt the execution of your application. But within the Try block, the execution of the code is halted only within that block, and control is passed to …
The Catch Block
The Catch block executes code once an exception is thrown in a Try block. It allows one to code an app in such a way that if some exceptions can be expected – such as a resource missing – then the app can gracefully recover from the error, inform the user what happened, and go on executing. The client wins, the app is happy, and you’re happy because you’ve written clean code!
} catch (err) {
displayError(err, data);
closeResource();
}
In the example above, the ‘err’ argument is the Error event that occurred. You can then parse this Error event (google it for details) and do whatever you need to do to get your app back up and running. In this case, we will display some sort of error, then close out the resource. The app will continue executing after the catch block as if nothing happened.
Throwing Errors
Sometimes you need to throw your own errors based upon data you may have received. For example, suppose your readResource() method would return an error message instead of throwing one. How would you handle that? By using the Throw statement.
Let’s change our code and take a look at it:
const resource = "./mydata.json";
let data, handle;
try {
({ data, handle } = readResource(resource));
if (data.error === true) {
throw new Error('Bad read on the resource file. Try again!');
}
data = processResource(data);
displayResource(data);
closeResource(handle);
} catch(err) {
displayError(err, data);
closeResource(handle);
}
Notice lines 6 through 8. If the ‘error’ property on the data returned from the readResource() method is true, then we have an error. Now, we choose to send our own error exception, and that is through the Throw statement. Using Throw will cause a JavaScript exception to occur, and if that is inside a Try/Catch block, you can then work on that exception just as you would any JavaScript exception.
Another thing is that you don’t have to use an “Error” object as I did above. Throw will ‘throw’ any variable. Personally, I like to use an Error object so that I am consistent with what JavaScript does when it throws an exception.
And Finally … Finally!
There is one additional part to the Try/Catch block I want to show you. That’s the Finally block, and it executes after the Try block executes or the Catch block executes. That is, it will always execute one time, once either the Try block or the Catch block completes.
Let’s change our code slightly and look at how Finally is used:
const resource = "./mydata.json";
let data, handle;
try {
({ data, handle } = readResource(resource));
if (data.error === true) {
throw new Error('Bad read on the resource file. Try again!');
}
data = processResource(data);
displayResource(data);
} catch(err) {
displayError(err, data);
} finally {
closeResource(handle);
}
Notice that the Finally block is mentioned after the Try block on the Catch block. What’s happening here?
- If the Try block completes, the Finally block will then execute.
- If an exception occurs in the Try Block, the Catch block will execute. Once that finishes executing, the Finally block will execute.
It’s that simple. The Finally block will execute after either the the Try block or the Catch block executes. To put another way – it will always execute.
This makes it a great place to put any ‘clean up’ code. Notice in the code snippet above that the method “closeResource” has been moved from being in both the Try block and Catch block (look at the previous examples) and is now only mentioned in the Finally block. This is a good thing. Given the first code snippet, if we had to add to the code before or after the ‘closeResource’, then it had to be done twice. Now, it only needs to be done once, and it’s guaranteed to execute.
See it Here
Of course, you can always check out our video on Try/Catch.
Be sure to subscribe to our YouTube channel!
Conclusion
And that’s all there is on the Try/Catch block. It’s a great tool to use if you want to have control over the exceptions that may occur with your app, and allow you to gracefully recover.
Categories: Boring JavaScript Javascript
thevirtuoid
Web Tinkerer. No, not like Tinkerbell.
Creator of the game Virtuoid. Boring JavaScript. Visit us at thevirtuoid.com
Leave a Reply