JavaScript Error Handling and Exceptions

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional Modern JavaScript Lessons

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36

JavaScript Error Handling and Exceptions

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Error Class

const basics = new Error('Something bad happened');

console.log(basics.message); // 'Something bad happened'

console.log(basics.stack);
/*
Error: Something bad happened
at Object.<anonymous> (/demo/src/index.js:1:16)
at Module._compile (node:internal/modules/cjs/loader:1165:14)
at Module._extensions.js (node:internal/modules/cjs/loader:1220:10)
at Module.load (node:internal/modules/cjs/loader:1035:32)
at Module._load (node:internal/modules/cjs/loader:876:12)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
*/

const rangeError = new RangeError('Wrong number');

console.log(rangeError.message); // 'Wrong number'
console.log(rangeError.stack);
/*
RangeError: Wrong number
at Object.<anonymous> (/demo/src/index.js:9:16)
at Module._compile (node:internal/modules/cjs/loader:1165:14)
...
*/

console.log(rangeError instanceof RangeError); // true
console.log(rangeError instanceof Error); // true

console.log(basics instanceof RangeError); // false
console.log(basics instanceof Error); // true

Runtime Errors

let person = {
name: 'John',
};

console.log(person.name); // 'John'

person = undefined;

console.log(person.name); // TypeError: Cannot read property 'name' of undefined

try / catch

try {
fancyModernStuff();
} catch (err) {
console.log('-instance of-');
console.log(err instanceof Error);
console.log('---message---');
console.log(err.message);
console.log('----stack----');
console.log(err.stack);
}

console.log('Yay! We Made it!');

throw

function sum(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('Parameters must be numbers');
}
return a + b;
}

console.log(sum(100, '100')); // Error: Parameters must be numbers

finally

try {
console.log('setup a db connection');
console.log('run a query');
} catch (err) {
console.log(err.message);
} finally {
console.log('make sure the db connection is closed');
}

rethrow

function doNotLikeOne(input) {
if (input === 1) {
throw new Error('I hate 1 - its too lonely');
}
console.log('I am happy');
}

function poke() {
try {
doNotLikeOne(1);
} catch (error) {
console.log(`~~ Monitoring: ${error.message} ~~`);
throw error;
}
}

poke();
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

A co-tenant of any programming language is how it deals with exceptions and of course it's a first class concept in JavaScript as well where it is called error handling. To kick us off, let's first take a look at the built-in error class. Here we have a simple instance of the error class created and stored in a basic variable. Now the constructor for the error takes a simple message value and we can actually access this from the rein instance by using the message property. Perhaps the most useful feature of the error class is the fact that it captures the stack trace into the stack member. It's just a simple string, but there are plenty of tools out there that help you process the string into

00:36

more meaningful ways. At its score, the string contains the error type, the error message along with the stack trace up until the point where the error class was created. Here we created the error line, one of our indexer chase, and the remaining stack trace actually shows some of the internals of the node js runtime that is executing this code. Beyond this space class, there are a few other error classes built into JavaScript as well and all of them inherit from this base error class. Once a child class is a range error. The key difference in these child classes is that the class name is going to be different,

01:09

which you can sort of use to hint on the kind of error that you are raising. For example, range error is conventionally used when you want to indicate the fact that a value is out of range. Now of course, because these are JavaScript classes, we can use the instance of operator on the created objects to check if they are an instance of a particular class. Additionally, because all errors inherit from the error class instance of with error will also return true. Of course, the base error instance that we created previously is going to return false as an instance of range error and only return true as an instance of error.

01:43

Now all of these trial classes inherit features from the base error class, which means that they still have the message property which gives the original message name as well as the stack property. The stack property is going to be the same as the base error class stack that we saw previously. The only difference is that the name is different. Here you can see that it says range error instead of error. Errors can happen for all sorts of intentional and unintentional reasons. For example, a common error in JavaScript is trying to access members of an undefined value. As a quick recap, we can access properties off of objects using the documentation.

02:16

So with the person object we can access person.name and of course it's going to point to that string, John. Now if we assign person to undefined and try the same thing again, the JavaScript on time will throw an error. In this particular case, the error class that the JavaScript runtime uses is called type error, which of course is still an extension of the base error class. If an error happens in your JavaScript code and you do not handle it, no further statements will execute in that stack. Which brings us to the topic of gracefully handling errors, which we can do with a dry catch. If you try to use a variable that is not defined anywhere and we just assume

02:52

that it's going to magically exist, of course the JavaScript runtime is going to throw an error. Now, as soon as it does that, any additional lines of code that we have are not going to execute. So this console log statement, yay, we made it is never going to turn up and if we execute this code, you can see it in the output. It only contains the reference error. That fancy modern stuff is not defined. A console log statement y made, it is no way to be found to gracefully handle the error and not have our program exit with code one, we need to wrap the offending code with a dry catch. Here we are telling the JavaScript runtime that try to execute this code and if

03:29

it doesn't work for whatever reason, catch that error and give it to me in the variable that we are calling E R R. So now that we are catching the error and not letting it leak all over our code base, you can see that the console log statement, yay, we made it can execute successfully. Now of course this error object that the JavaScript runtime throws is going to be of type error, which means that if we do instance off error is going to return true is going to contain the message property and it is going to contain the stack property. And if you run this code, again, you can see our assumptions being verified by the program output.

04:02

This particular error is of type reference error, but of course since it does still inherit from error, error instance of returns too, even though errors can happen naturally in JavaScript, you can always throw errors yourself. For example, when some value isn't behaving the way that you expect it. Consider the simple sum function that takes two variables, A and B and decides to return the sum and we expect both A and B to be of type number, but this is JavaScript which means that people can come along and pass in some numbers and some strings. Now ideally we would want an error, but this is JavaScript, which means everything is going to be fine.

04:36

It's going to give us this concatenated string and we were really expecting the number 200. Fortunately, we can early fail on silly mistakes like this ourselves we can just check if type of A is not equal to number or type of B is not equal to number and if either of these conditions are true, we can throw our own error with the message parameters must be numbers and instead of getting this random string which is going to cause issues elsewhere, we get a much more reliable developer experience of an error being thrown up front. So when we look at the console,

05:08

we can see that we are making a mistake that the parameters must be a number when we are invoking the sum function. When an error happens in JavaScript, it'll automatically start propagating back through the call stack till it gets handled by a cat statement. Consider the simple function called tantrum, which always throws an error no. So when we invoke it from another function for example, come here, of course it's going to throw an error. So now if you make a call to come here, come here, we'll also throw that error and we can actually catch it over here and log out the message for the error object. So we invoke come here, come here,

05:43

invoke rum tantrum, throws an error and we catch that all the way at the top in our root dry catch. Of course, the whole objective of catching an error is that it no longer propagates. For example, if you have a big boy function that throws an error but it doesn't leak anywhere. We catch it immediately within that function. If we invoke big boy and wrap it up in a dry catch, that error is already caught within big boy and this particular outside catch will never get invoked. With the JavaScript dry block, you can optionally add a finally block to make sure any cleanup required happens irrespective of an error.

06:17

Consider the simple scenario where we have within a try block the desire to open a DB connection and run a query and we want to catch any errors that might happen within the try using a simple catch block. And finally, irrespective of whether an error happens or not, we want to make sure that the database connection is closed irrespective of whatever happens in the trial. The catch block, the finally block will always execute, so no surprise in this particular example, the trial block will execute. There are no errors that can happen in try, so catch will not execute and then finally we'll execute and we can verify that from the console.

06:52

Let's modify our code to represent the scenario where we have a failed attempt to run a query by simply throwing a new error. And in this particular example, the try block will execute because we throw an error, the catch block will execute and of course the finally always executes and that is what we see on the console. J script actually allows you to skip the catch entirely as well. So we can actually just use a try and a finally, and in this particular example, the try block will execute, it'll throw an error, but before that error propagates, the finally block will execute and we can see that when we run the code,

07:25

we see the log from the try, we see the log from the finally, and then we see the error that we didn't catch, which propagated all the way to the node JSS runtime logging that error to the console. One thing to be aware of for the try-catch is that it only catches errors that execute in the same synchronous code Block. Here We have a try block Within which we set a timeout and we try to invoke a function. We exist in the matrix, which is a function that doesn't exist, so we totally expect it to throw a reference error and to catch that we wrap it up, up with the catch block. We we log out,

07:58

we have Neo now let's walk through how this code is going to execute. We are going to execute the trial block within which we will invoke set timeout and then the trial block will actually D terminate and since no error has happened right now nothing will be caught and eventually after one second, which is the timeout that we have set up, set timeout is going to start executing the function. We exist in the matrix and because right now when set timeout is executing that function, it is not in the presence of any try and catch, which means that the error will happen and it'll propagate all the way to the node JS runtime which will log it to the console. Now if you

08:31

Want to catch this error using a Try-catch, we need to put the try-catch in the same synchronous code block that is resulting in the error. We Refactored our code To make sure that we exist in the matrix is a Wrapped by our try-catch And now instead of it being handled by the note J runtime, we will catch It effectively And simply log out. We have Neo and if you run this code, you can see that That is exactly What happens. There is a key difference in how the server code like node js handles uncaught errors versus how they are handled by all the browsers. Consider the simple code where we set up a timeout to invoke a function.

09:05

It's all in your imagination, which does not exist, so we totally expect this to throw an error and then we set a timeout for two seconds to log out my own universe. Now here's how the program execution is going to go. After one second, it'll try to invoke, it's all in your imagination, it'll throw an error and because this is running in no js, it's going to result in a program failure and the second time out, my own universe will never execute, which is why we do not see that statement anywhere in the console. This makes a lot of sense in a server environment because we don't want an unreliable process running around perhaps corrupting one user's data with

09:40

another user's information. It is better to let the whole process exit, log into a monitoring service and then just restart the process to make sure that you have a clean good state. This is different from how we want the browsers to operate. If you take the same code and paste it into a browser console, what will happen is that after one second we do get that error that it's all in your imagination. It does not exist, but the website doesn't crash and after two seconds we still get the log from the second timeout, which logs a my own universe and this makes more sense for a browser environment where we don't want the whole website to fail just because a single HTTP request

10:16

failed. This is also why sometimes you find that the website will not be doing what you want. For example, you click a button and nothing happens. That's probably because there is an error on the click handler, but that's not going to result in the whole website crashing on you. Perhaps you can try different things on the website. For example, press the back button and then you press the next. Now that button that you are clicking will start working again. Browsers only unwind the current synchronous stack and do not crash the whole website in the presence of an uncaught error. One best practice to always follow that beginners and certain tutorials often forget is that you should never ever throw plane strings as errors. A,

10:52

we have a simple function alpha that tries to be helpful, tries to throw a helpful message, but does not wrap it up in an error object, and this is not good enough to demonstrate that. Consider a more real world scenario where alpha is invoked by petita, which in turn is invoked by gamma and we do catch the error that will happen when gamma gets invoked and log that error to the console. Unfortunately, since Alpha decided to throw a string instead of an error object, that is exactly what we get within the CAD statement and if we log it out to the console, we only see this message and we have no idea what is the code execution that resulted in this particular error.

11:28

Compare this to the simple fix where we wrap our error message in an error object and now execute this code again. Now we have a much clearer idea that an error has happened with the message. Helpful message at Alpha, which was in worked by beta, which was in worked by Gamma from our main application source index js. A common pattern with knowing about when it comes to error handling is that sometimes we handle an error only for logging and monitoring purposes and then immediately read through it to let it proceed to its potentially uncaught failure. For example,

12:00

here is a simple function that just has some pet peeve against the number one. I don't know why it hates it. It says that it hates it because it's too lonely, but I'm not so sure about it. If the input however is not one, then this function will be happy. And just like in the real world, there is a function called poke that just likes to invoke do not like one with the one value it doesn't like, which is one Poke, however, only wants to try to catch this error for logging and monitoring purposes. For that it adds a CAD statement, logs the error off to a monitoring service, and then because it doesn't want to handle it properly,

12:33

it simply trows that error for someone else to handle this pattern of catching an error and only looking at its few properties for monitoring purposes. And then throwing it is a common pattern that people use when you do not expect an error. But when an error does happen, you do not want to ignore it. You want to be notified about that fact. However, you do not want your program to be unreliable, which is why you still throw that error again and to demonstrate that let's just run the spoke function and execute this code. You can see that because of that rero that we didn't catch, the program has exited, but before it did, we did get the opportunity to log that error off to a monitoring service,

13:09

which in our case is just a simple console log. I'll wrap things up there. As always, thank you for joining me on this lesson on JavaScript error handling and I will see you in the next one.

Professional Modern JavaScript

Professional Modern JavaScript

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36