Error  Handling  In  Js

Error Handling In Js

Introduction :

If we write javascript code there might be some chance of getting errors don't be afraid this is part of programming. By producing errors, we learn how not to do something and how to do it better next time. There are a lot of types of errors like logical errors, syntax errors, type errors etc. but some of the errors might be catching on compile time but what about logical errors also when we get some data from the server it takes some time and what if the data won't retrieve from the server for some reason. For gives users a better experience that they don't see our script errors and have to see some desirable message. Javascript introduces Exception handling. If there is no exception handler, the program returns whatever function caused the error.

Does it necessary to use exception handling??

yes, it might be or not. let me tell you why suppose we have to write a code that takes two numbers input a,b and we have to divide 10 by (a-b). On our side, we write clean code but what about the client side suppose a user has input a and b both values same then 10 divided by 0. This gives an infinite output and users have a bad experience and they won't come back to our website. Let's do this practically for a better understanding

let a = 15;
let b = 5;
console.log(10/(a-b)); // output will be 1
a = 12;
b = 12;
console.log(10/(a-b)); // output will be infinite

That's why we use exception handling to control errors and give users a better experience. If you write a small code for your understanding you don't need to use exception handling but if your code has been sent to the production level for the better practice you have to use exception handling. we don't want at the production level any error occurs the remaining code will not execute and our website will crash.

In general, exceptions are handled in two ways:

First, we discuss Throw Statement,

Throw an exception :

If you’ve been using JavaScript for a long time, you may have seen something like ReferenceError: XYZ is not defined. This represents an exception that was thrown via a throw statement.

Syntax

// throw  value;

if (!a) {
    throw 'The error thrown by throw statement'; // this throws an error
}

If there is a problem that can’t be handled meaningfully where it occurs at runtime, it’s best to throw it.

An example for a better understanding of throw statement,

const GetName = (Name)=>{
    if(Name){
        console.log(`your name is ${Name}`);
    }
    else{
        throw new Error('Give Me your Name '+Name);
    }
}

GetName("Umesh"); // output :- your name is umesh
GetName(); // Uncaught Error: Give Me your Name undefined

Here you see new Error("message") let's know something about this...

Error Objects

There is no restriction on the type of data that can be thrown as an exception, but JavaScript has special built-in exception types. One of them is an error, as you saw in the previous example. These built-in exception types give us more details than just a message for an exception. Error objects are thrown when run-time errors occur and it will give user-defined exceptions.

TRY CATCH...

Try catch is the simplest way to handle the exception. The try-catch statement mainly has two blocks try and catch. As the name defines the work of the block like try it defines first try the code written inside the block if any error occurs inside the block or the server takes too long time to give data then go to the catch block. we can also say that we want to succeed try block but it doesn't have to pass the control to the catch block. If any statement within the try block and a function call within the try block gives an error then immediately control shifts to catch block. If there is no exception in the try block then the catch block is skipped.

Syntax Of Try Catch:-

    try{
       // code may cause error
    }
    catch(exception)
    {   // code to handle error 
        // and give some desirable output
    }

The catch block is used to handle all the exceptions that have been generated in the try block. In the catch block parameter, it takes the exception thrown by the try block. You can use this parameter to print the exception occurring in the try block.

The theory is very overwhelming let's take some examples to understand more

//console.log(a); // here we doesn't declare a and we use it this will give us reference error and programm execution will stop
try{
console.log(a); // but here we use this inside the try catch so it will give error and execute remaining code
}
catch(e)
{
    console.error("Aww you doesn't declare variable a very bad");
}

console.log("hello code is executed");

The output will be like this -

Here you notice that I was using the console.error() instead of console.log() in the previous example because when logging errors to the console inside a catch block, using the console.error() rather than console.log() is advised for debugging. It formats the message as an error and adds it to the list of error messages generated by the page. If we don't use console.error() to print the error and use console.log() the output will be like this

Here you see the difference the error is printed but in the output format not in the error format. That's why we use a console.error() inside the catch block.

You can also print the error thrown by try block using the catch parameter like this

try{
console.log(a);
}
catch(e)
{
    console.error("Error thrown by try block is ::: ", e); // Error thrown by try block is :::  ReferenceError: a is not define
// ReferenceError: a is not define :- this will print by e
}

console.log("hello code is executed");

Try-catch works Synchronously If an exception is happen in the scheduled code like in setTimeout() . Then try-catch won't catch it. let's take an example and understand it better...

try{
    setTimeout(() => console.log(a), 1000);
}
catch(err)
{
    console.error("In the Catch Block the error is = ",err);
}
console.log("remaining code");

First, you think about what will be the output of that code. According to what we've understood so far the output will be like this...

remaining code
In the Catch Block, the error is = ReferenceError: a is not define

Because the setTimeout() is a wepApi so first the remaining code will print and after this, it goes to setTimeout() callback function and here it found variable a is not declared so it gives an error and goes to catch block, right? But here is a twist the output will be like this...

Have you ever noticed one thing error will be only ReferenceError: a is not defined instead of In the Catch Block, the error is = ReferenceError: a is not defined. This means it doesn't go to catch block and gives an error inside the setTimeout() . This happens because the setTimeout() delays the execution of a function that prints the value of the variable a by 1 second. However, the variable a is not defined in the code, which means that attempting to print its value will result in a ReferenceError.

Since the setTimeout() is an asynchronous function, the try-catch block will not be able to catch any errors that occur during the execution of the delayed function. Instead, the error will be printed to the console by the JavaScript engine.

After calling setTimeout, the code continues to execute synchronously and prints the "remaining code" to the console. Then, after 1 second, the delayed function executes and throws a ReferenceError.

Hope you understood Why the output will not be according to our understanding.

After all this, you must be thinking that how do we handle it ?

So, for resolving this situation we have nesting try...catch statements

NESTED TRY...CATCH

We can use try-catch inside the try-catch statements.

Syntax:

try {
  // Code block that may throw an error
  try {
    // Code block that may throw another error
  }
  catch (innerError) {
    // Handle the inner error
  }
}

catch (outerError) {
  // Handle the outer error
}

You have seen that there are two try-catch blocks: an outer one and an inner one. The code in the outer block may throw an error, and if it does, the error will be caught and handled by the outer catch block.

Within the outer try block, there is an inner try block. If the code within the inner try block throws an error, it will be caught and handled by the inner catch block. If the error is not caught in the inner catch block, it will propagate up to the outer catch block.

Let's solve the previous example using nested try-catch

try{
    setTimeout(() =>{ 
    try{
        console.log(a);
        }
        catch(innerError){
        console.error("error inside setTimeout : ", innerError);
        }
    }, 1000); 
}
catch(outerError)
{
    console.error("OuterError = ",outerError);
}
console.log("remaining code");

For setTimeout() callback function we use another try-catch for handling the error inside the callback function. And here is the output

I hope now you know a little bit about the try-catch statements.

How do we find and fix errors?

To find and fix errors you should know how to debug your code and to do clean coding. By debugging you can improve your code quality and reduce development time.
Here is some common debugging technique that you should know.

  1. Console.log(): This is one of the most common debugging techniques used by JavaScript developers. Console.log() is a method that prints the value of a variable or object to the browser console, allowing you to inspect its value and behaviour.

  2. Code review: Sometimes, it can be difficult to find errors in your code. In these cases, it can be helpful to have another developer review your code and provide feedback.

In summary, debugging is an ongoing process that requires continuous attention and effort, but the benefits of effective debugging are well worth the time and resources invested.

Key takeaways

Let’s review some of the main points we discussed in this blog.

  • The throw statement is used to generate user-defined exceptions. During runtime, when a throw statement is encountered, execution of the current function will stop and control will be passed to the first catch statement in the call stack. If there is no catch statement, the program will terminate

  • JavaScript has some built-in exception types, most notably Error.

  • The try statement will contain code that could potentially generate an exception

  • The catch statement will be executed when exceptions occur.

  • Nested try-catch is used if any async function is inside the first try block.

  • An unhandled exception can be caught, which can prevent the app from crashing.

Conclusion

Exception handling is a critical part of writing reliable JavaScript code. By handling exceptions, developers can prevent unexpected behaviour, avoid application crashes, and provide users a better experience.

Overall, exception handling is an ongoing process that requires continuous effort. By investing the necessary time and resources, developers can ensure that their applications can handle unexpected situations effectively. When done properly throughout, exception handling can help you improve the maintainability, extensibility, and readability of your code.