Errors handling

Faillure case scenarios

As you have noticed from now, JavaScript is a very flexible language, allowing you to perform things that is usually not possible in more conventional language like Java or C (e.g. non-typed variable and polymorphism). However, the drawback of this flexibility lays often in code instability and weird behaviors (this has an important part to do here).

Exploiting the non-typed approach of JavaScript, a way to allievate weird behaviors is to heavily rely on return; to stop the execution of a function that either does nothing to do, or has face a faillure/unauthorised case. To foster maintenable code, and well documented, the checkings is often made at the begin of the function -- regrouping all the verification in a single place which can be easily documented.

function foo(var1, var2, callback){
    if(!callback) //if callback is null or undefined, we stop here
        return; //return undefined
    if(var1 < 0)
        return;
    if(var2 > var1*this._someGlobalVar)
        return;
    if(!this.registerCallback(callback))//callback already exists for example
        return;

    // Now we can run the function's code
}

That is why you want to rely on get and set for your class! You can handle these scenarios and sometimes correct them with default behaviours (e.g. set a negative variable to 0).

Errors

However, no matter how hard you try, your code will fail one time or another (because of you, the user, the hardware, etc.). Despite return is a good approach in several cases, sometimes you need more powerful error managment. Indeed, when your script fails, it usually "dies" -- stops immediatly. However, maybe you want to recover from this error and do some specific actions instead of stopping your script (e.g. reinitializing your interface).

A constructor should never failled! If it fails, an error should be thrown, or the construction of the object should be delegate to a builder (cf. Builder pattern): there should not be other possibility IMO.

Try...catch

JavaScript, as several other language, introduced the try...catch syntax:

When JavaScript arrives on a try...catch statement, first the code in try is executed. If no error are thrown inside this block, then the catch block is ignored. Otherwise, the rest of the try block is ignored once an error is thrown. The error is then handled by the catch block and stored in a variable (here error). Consequently, an error does not stop your script of running if it happens in a try block.

The catched error by catch is also an object. The built-in erros has the following useful properties:

  • name

  • message

  • stack

Finally

There is an additionnal clause to the try...catch which is finally. If attached to a try or a try...catch statement, the content of the finally block is always executed. This is usefull to end/finalise something that has been started. For example, closing a communication socket. The syntax:

The finally clause works for any exit! That means if you return from a try or block explicitly, you will land in the finally block!

Custom error and throwing

You can produce your own error during the execution of your code. For example, parsing a JSON string and noticing that there is no information about an expected state of a game (i.e. gameState is set to undefined). To do so, we simply use the throw keyword:

Error is the super type of all the errors in JavaScript. But there is more specific built-in errors, like SyntaxError, that can be used as Error depending on the situation.

When you throw an error, you create an exit point in code: all the instructions below are no longer executed (like a return).

In a complete example:

You can rethrow a handled error in a catch. Rethrowing is used when the error received cannot be correctly handled where it happens and needs to go back up the execution stack.

You can define your own errors by extending the built-in errors in the language, like any class. And then use it as any other errors:

A good practice in your custom error could be to keep a reference on the object which has failed.

Error and synchronicity

An important things to note is that try...catch works synchronously. In other words, if an error happens in a "scheduled" code, like in a event callback or in TimeOut, try...catch will not catch it. That is because the function is executed later in the code, when the engine has alread left the statement.

Thus, to catch an error in an asynchronous, the try...catch need to be in this very function!

In addition, in the case of a async/await situation, it is possible for a promise rejects an error, just as if there were a throw statement at the line of the .reject(new Error).

However, in real situation, the promise will take some times before it rejects. In that case, we can use try...catch to catch the error throw by awaiting.

You can wrap multiple await line in one try as showed above!

If you don't use try...catch, you can still catch the error by using the .catch statement when f() becomes a rejected promise: f().catch(alert).

Browser debug

Use your browser to debug your code!! A good tutorial from the Chrome DevTools.

Last updated

Was this helpful?