JS Error Handling

Sometimes when you run your JavaScript code it doesn’t run smoothly as expected and even results in an error. There are so many reasons that may cause errors, it could be any of the following:

  • Network connection problem
  • The user might have entered an invalid value in the form field
  • Referencing an object or function that does not exist
  • Sending or receiving of incorrect data from the web server
  • The service that the application needs to access might be temporarily unavailable

 

These errors are known as runtime errors because they occur at the time the script runs. All professional applications should have the capabilities to handle such runtime errors efficiently. It usually involves informing the user about the problem more clearly and precisely.

 

The try...catch Statement

The try-catch statement is provided by JavaScript to trap the runtime errors and handle them efficiently.

A code that might possibly throw an error must be placed in the try block of the statement, whereas the code to handle the error is placed in the catch block, as shown in the example below:

try { 

    // Code that may cause an error

 } catch(error) { 

    // Action to be performed when an error occurs

 }

 

In the case where an error occurs at any point in the try block, the code execution is immediately transferred from the try block to the catch block. However, if no error occurs in the try block, then the catch block will be ignored, and the program will continue executing after the try-catch statement.

The examples below illustrate how the try-catch statement actually works:

try {
    var greet = "Hi, there!";
    document.write(greet);
    
    // Trying to access a non-existent variable
    document.write(welcome);
    
    // If error occurred following line won't execute
    alert("All statements are executed successfully.");
} catch(error) {
    // Handle the error
  alert("Caught error: " + error.message);
}
 
// Continue execution
document.write("<p>Hello World!</p>");

In the example above the script will generate an error that is displayed in an alert dialog box, instead of printing it to the browser console. However, the program didn't stop abruptly even when an error occurred.

Note: The catch keyword is always followed by an identifier in parentheses. This identifier simply acts as a function parameter. In the case where an error occurs, the JavaScript interpreter generates an object containing the details about the error, and this error object is then passed as an argument to catch for handling.

Tip: The try-catch statement acts as an exception handling mechanism. An exception is simply a signal that indicates that some sort of exceptional condition or error has been triggered during the execution of a program. However, the terms "exception" and "error" are mostly used interchangeably.

 

The try...catch...finally Statement

Most importantly, the try-catch statement can also have a ‘finally’ clause. The code inside the finally block will always execute, notwithstanding if an error has occurred in the try block or not.

The example below will display the total time taken to complete the execution of the code.

// Assigning the value returned by the prompt dialog box to a variable
var num = prompt("Enter a positive integer between 0 to 100");

// Storing the time when execution start
var start = Date.now();

try {
    if(num > 0 && num <= 100) {
        alert(Math.pow(num, num)); // the base to the exponent power
    } else {
        throw new Error("An invalid value is entered!");
    }
} catch(e) {
    alert(e.message);
} finally {
    // Displaying the time taken to execute the code
    alert("Execution took: " + (Date.now() - start) + "ms");
}

 

Throwing Errors

In the previous tutorial and this one, you have seen the errors that are automatically thrown by the JavaScript parser when an error occurs. But, it is possible to throw an error manually by using the throw statement.

In addition, the general form (or syntax) of the throw statement is ‘throw expression’.

The throw expression can be an object or a value of any form of data type. Also, it is preferable to use objects with name and message properties. However, JavaScript built-in Error() constructor provides a convenient and easy way to create an error object. Take a look at the example below:

throw 123;
throw "Missing values!";
throw true;
throw { name: "InvalidParameter", message: "Parameter is not a number!" };
throw new Error("Something went wrong!");

Note: When using the JavaScript built-in error constructor functions (e.g Error(), TypeError(), and so on.) for creating error objects, as the name property is the same as the name of the constructor, as a result, the message will be equal to the argument passed to the constructor function.

Let’s create a function squareRoot() that will find the square root of a number. This is done by simply using the JavaScript built-in function Math.sqrt(), however, the problem is, it returns NaN for negative numbers, without providing any hint on what has gone wrong.

So, let’s fix this problem by throwing a custom error if a negative number is supplied.

function squareRoot(number) {
    // Throw error if number is negative
    if(number < 0) {
        throw new Error("Sorry, can't calculate square root of a negative number.");
    } else {
        return Math.sqrt(number);
    }
}
    
try {
    squareRoot(16);
    squareRoot(625);
    squareRoot(-9);
    squareRoot(100);
    
    // If error is thrown following line won't execute
    alert("All calculations are performed successfully.");
} catch(e) {
    // Handle the error
    alert(e.message);
}

Tip: Theoretically it is possible to calculate the square root of a negative number with the use of the imaginary number ‘i’; where i2 = -1. Hence, the square root of -4 is 2i, the square root of -9 is 3i, etc. in contrast, imaginary numbers are not supported in JavaScript.

 

Error Types

The Error object is the basic error type for all errors and it has two main properties: 

  • A name property that specifies the type of error. 
  • A message property that holds a message describing the error in more detail. 

There are different types of errors that can occur during the execution of a JavaScript program, like RangeError, ReferenceError, SyntaxError, TypeError, and URIError.

The sections below describe each one of these error types in detail:

 

RangeError

A RangeError is thrown when a number that is outside the range of allowable values is used. For instance, creating an array that has a negative length will throw RangeError.

var num = 12.735;
num.toFixed(200); // throws a range error (allowable range from 0 to 100)

var array = new Array(-1); // throws a range error

 

ReferenceError

This type of error is thrown when trying to reference or access a variable or object that doesn't exist. The example below shows how the ReferenceError occurs.

var firstName = "Harry";
console.log(firstname); // throws a reference error (variable names are case-sensitive)

undefinedObj.getValues(); // throws a reference error

nonexistentArray.length; // throws a reference error

 

SyntaxError

The SyntaxError error is thrown at runtime when there is any syntax problem in your JavaScript code. Take, for example, if a closing bracket is missing, loops are not structured properly, etc.

var array = ["a", "b", "c"];
document.write(array.slice(2); // throws a syntax error (missing bracket)

alert("Hello World!'); // throws a syntax error (quote mismatch)

 

TypeError

This type of error is thrown when a value is not of the expected type. For instance, calling an array method on a string, calling a string method on a number, etc.

var num = 123;
num.toLowerCase(); /* throws a type error (since toLowerCase() is a string method, a number can't be converted to lowercase) */

var greet = "Hello World!"
greet.join() // throws a type error (since join() is an array method)

 

URIError

The URIError error is thrown when an invalid URI (Uniform Resource Identifier) is specified to the URI-related functions like the encodeURI() or decodeURI(), as shown below:

var a = "%E6%A2%B";
decodeURI(a);  // throws a URI error

var b = "uD800";
encodeURI(b);   // throws a URI error

Note: There is another error type called ‘EvalError’. It is thrown when an error occurs during the execution of code via the eval() function. however, this error is not thrown by JavaScript anymore, but this object remains for backward compatibility.

The specific error type can as well be thrown manually with the respective constructor and the throw statement, for instance, to throw a TypeError you can use the TypeError() constructor, as shown below:

var num = prompt("Please enter a number");

try {
    if(num != "" && num !== null && isFinite(+num)) {
        alert(Math.exp(num));
    } else {
        throw new TypeError("You have not entered a number.");
    }
} catch(e) {
    alert(e.name);
    alert(e.message);
    alert(e.stack); // non-standard property
}

Note: The Error object also supports a few non-standard properties. An example is a widely used property known as ‘stack’, which returns the stack trace for that error. It can be used for debugging purposes, however, do not use it on production sites.