ECMAScript Error Handling Tutorial (ES6)

View more Tutorials:

1- What is Error?

First of all, let's look at an example, in which I call a method of an object, but this object actually does not have this method, and the error occurs.
hello-error-example.js
console.log("Three");

let myObj = {};

console.log("Two");

console.log("One");

// Object myObj has no showMe() method.
// But we call showMe().
// And error occur here.
myObj.showMe(); // ==> Error!!!!!!!!!


// And the following code will not be executed.
console.log("Let's go!");
The result from running the example:
You can see the notification on the Console screen. The error notification is very clear, including the information of code line.
Please have a look at the flow of the program through the following illustration.
  • The program runs completely normally in steps (1), (2), (3), (4)
  • In step (5) an error occurs when you are trying to call an object method while this object doesn't have that method .
  • Code in step (6) will not be executed.

2- Handling error with try-catch

Errors may occur in the runtime of the program. it may be an unexpected error.   Use  try-catch helps you catch and handle errors when they happen.
Come back to the above example, we add  try-catch to catch and handle errors.
hello-catch-example.js
console.log("Three");

let myObj = {};

console.log("Two");

console.log("One");

try {
    // Object myObj has no showMe() method.
    // But we call showMe().
    // And error occur here.
    myObj.showMe(); // ==> Error!

    // This code will be ignored
    console.log("!!!");

} catch (e) {
    console.log("Catched error: " + e);
    console.log("OK continue...");
}

console.log("Let's go!");
And the results of running the example:
The following illustration explains the flow of the program:
  • The steps (1)-(4) are completely normal.
  • An exception occurs in step (5), when you try to call a method of an object, while this object does not have this method.
  • Immediately it jumps in to execute the command in the catch block. Step (6) is ignored.
  • Steps (7), (8) will be executed.
  • Step (9 will be executed.

3- try-catch-finally

We have got accustomed with catching error through try-catch block. try-catch-finally is used to fully handle error. The finally block is always executed, regardless of whether the error occurs in the try block or not.
try {  
   // Do something here.
} catch (e ) {
  
   // Do something here.
} finally  {
   // The finally block is always executed.
   // Do something here.
}
Example:
try-catch-finally-example.js
function getGreeting(language) {
    try {
        console.log("Code in try block (*)");

        // Call greeting() method of object 'language'
        // An Exception can throw here if this object has no greeting() method.
        let v = language.greeting();

        console.log("Code in try block (**)");

        return v;

    } catch (e) {

        console.log("Code in catch block. Something Error: " + e);

    } finally {
        // The finally block is always executed.
        console.log("Code in finally block");
    }

    return " !! ";
}

// ----------------------- TEST ---------------------------------
// Test 1:
console.log("----- Call getGreeting(null) -----");

let v1 = getGreeting(null);
console.log("Greeting: " + v1);


// Test 2:
console.log("------ Call getGreeting(language) ------");

let language = new Object();

language.greeting = function() {
    return "Hello Everybody";
}

let v2 = getGreeting(language);

console.log("Greeting: " + v2);
Running the example:
The following illustration is the flow of program if an error occurs in the try block, the finally block is always executed.
The following figure shows the flow of the program when no errors occur in the try block. In this case the finally block will be executed immediately before the return command of the try block  is executed.

4- Built-in Errors

ECMAScript has several available classes to represent an error. Below is their hierarchy.

RangeError

A RangeError is thrown if you use a number outside the allowable range.
error-RangeError-example.js
let num = 1;
try {

  // A number cannot have 500 significant digits
  num.toPrecision(500); // ==> RangeError!!
 
}
catch(err) {
  console.log(err.name);
  console.log(err);
}

ReferenceError

A ReferenceError is thrown if you use a variable that has not been declared:
error-ReferenceError-example.js
var x;
try {
  x = y + 1;   // y cannot be referenced (used)
}
catch(err) {
   console.log("Error Name: "+ err.name);
   console.log(err);
}

SyntaxError

A SyntaxError is thrown if you try to evaluate code with a syntax error.
error-SyntaxError-example.js
try {
  let x;
  eval(" x  = 'Hello  ");   // Missing ' will produce an error
}
catch(err) {
  console.log("Error Name: " + err.name);
  console.log(err);
}

TypeError

A TypeError  is thrown if you use a value that is not of the expected type. For example, an error occurs when you call a method of an object, while this object does not have that method.
error-TypeError-example.js
var num = 1;
try {
  num.toUpperCase(); // Number has no method toUpperCase()
}
catch(err) {
  console.log("Error Name: " + err.name);
  console.log(err);
}
 

URIError

A URIError is thrown if you use illegal characters in a URI function:
error-URIError-example.js
try {
  decodeURI("%%%");   // You cannot URI decode percent signs
}
catch(err) {
  console.log("Error Name: " + err.name);
  console.log(err);
}
See also:

5- Throw Error

ECMAScript allows you to throw anything in the runtime of the program. The program will consider an error has just happened.
throw-any-example.js
console.log(" -------- Test throw any object ------------");

try {
   let myObj = {};
   throw myObj;
} catch(e)  {
   console.log("Catch error: ");
   console.log(e);
}

console.log(" -------- Test throw a Symbol ------------");

try {
   let mySymbol = Symbol();

   throw mySymbol;
} catch(e)  {
   console.log("Catch error: ");
   console.log(e);
}

console.log(" -------- Test throw a Number ------------");

try {
   let myNumber = 100;

   throw myNumber;
} catch(e)  {
   console.log("Catch error: ");
   console.log(e);
}

console.log(" -------- Test throw a String ------------");

try {
   let myString = "Some error";

   throw myString;
} catch(e)  {
   console.log("Catched error: ");
   console.log(e);
}
 
Normally, you will use an Error class to create an error object. Other classes, such as SyntaxError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError can also be used in a suitable context.
An error object is created through the Error class (or its child classes). When being thrown, it will contain important information like the file where the error occurs, the location of the error, and the information helps you detect errors.
throw-error-example.js
console.log("Three");

// Create an Error
let myError = new Error("Something error!");

console.log("Two");

// Throw it!
throw myError;

console.log("One");
In the simple case, you can throw any object, not the object of the Error class (or its childclasses). However, when catching these types of errors, you will not have the information such as the file of the error, the location of the error, etc.
throw-string-error-example.js
console.log("Three");

try {

  console.log("Two");

  // Throw a String!
  throw "Some error!!";

} catch(e)  {
   console.log("typeof e = " + (typeof e));
   // Log the error
   console.log(e); // Some error!!
}

console.log("One");
In the  ECMAScript, each try block has a corresponding cache block. But there may be many types of errors in the try block, in which case you need to check the error caught in the catch block to provide appropriate handlings corresponding to each type of error.
catch-complex-example.js
let err = new Error("My Error");
let rangeErr = new RangeError();
let evalErr = new EvalError("My Eval Error");

// A random value in [0.. 9]
let randomValue = Math.floor(Math.random() * 10);

// [0,1,2,3]
let random0123 = randomValue % 4;

console.log("random0123 = " + random0123);

try {
   if(random0123 == 0) {
      throw err;
   } else if(random0123 == 1){
      throw rangeErr;
   } else if(random0123 == 2)  {
      throw evalErr;
   } else if(random0123 == 3)  {
      throw "A String Error";
   }

} catch(e)  {
   console.log("typeof e = " + (typeof e));// 'object' or 'string'

   if(e instanceof RangeError) {
      console.log("--> RangeError!!");
   } else if(e instanceof EvalError) {
      console.log("--> EvalError!!");
   } else if(e instanceof Error) {
      console.log("--> Error!!");
   } else if (typeof e == "string"){
      console.log("--> String Error!!");
   } else  {
      console.log("--> Error!!");
   }

   console.log(e);
}

6- The properties of Error

In the  ECMAScript, the error caught by you may be a  "Error object" or any error type. If it is a  "Error object" you will obtain the important information such as the name of file of error, error position, Stack Trace,..
There are some important  properties of the   Error class:
  • name: Name of error
  • message: Content of error
  • stack (Readonly): a string containing information helping you detect the position of error.
error-properties-example.js
// Create an Error
let myError = new Error();

myError.name = "MyError";
myError.message = "My Error String";


try {

  throw myError;

} catch(err)  {

  console.log("Error Name: " + err.name);
  console.log("Error Message: " + err.message);
  console.log("Type of err.stack: " + (typeof err.stack));

  console.log("--- Stack Trace: ---");  
  console.log(err.stack);
}

 

7- Re-throw Error

While handling the exception, you can catch that exception and handle it or you can re-throw it.
rethrow-example.js
function checkScore(score) {
    if (score < 0 || score > 100) {
        throw "Invalid Score " + score;
    }
}

function checkPlayer(name, score) {

    try {

        checkScore(score)
    } catch (e) {
        // Do something with the Exception
        console.log("Something invalid with player: " + name + " >> " + e);

        // Then re-throw this Exception.
        throw e;
    }

    console.log("OK Player " + name + " has score: " + score );
}



// --------------- TEST --------------
checkPlayer("Tom", 90);

checkPlayer("Jerry", -10);
For example, catch an exception and throw an other exception.
rethrow-example2.js
function checkScore(score) {
    if (score < 0 || score > 100) {
        throw "Invalid Score " + score;
    }
}

function checkPlayer(name, score) {

    try {

        checkScore(score)
    } catch (e) {
        // Do something with the Exception
        console.log("Something invalid with player: " + name + " >> " + e);

        // Then throw other exception
        throw ("Score " + score +" invalid for player " + name);
    }

    console.log("OK Player " + name + " has score: " + score );
}



// --------------- TEST --------------
checkPlayer("Tom", 90);

checkPlayer("Jerry", -10);

8- Exceptions when catching errors

In the  ECMAScript there are the situations that you think that a error will occur but it doesn't happen. For example, a number divided by 0 will not cause an error, the result returns   Infinity or  -Infinity.
ex-Infinity-example.js
console.log( typeof Infinity ); // number

let a = 1 / 0;

console.log(a); // Infinity

let b = -1 / 0;

console.log(b); // -Infinity
 
Divide a value other than a number by a number, the result is  NaN ( Not a Number).
ex-NaN-example.js
console.log( typeof NaN ); // number
console.log( isNaN(1) ); // false
console.log( isNaN( NaN ) ); // true

let a = "A String" / 2;

console.log(a); // NaN

let obj = {};
let b = obj / 2;

console.log(b); // NaN
You can access an element with any index of an array without causing an error.
ex-array-index-example.js
let myArray = [1, 100, 20];

console.log( myArray[1]); // 100

console.log( myArray[10] ); // undefined

console.log( myArray[-10] ); // undefined
 

View more Tutorials: