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.
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).
My advice is to break hard and break soon! Even if your code growth in size and take you more time by doing so, this is always a good practice, and it will help you when your code will become important.
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
Variable inside try...catch
are local! You cannot declare a new variable inside a try
block and use it elsewhere. This gives some confusion at the beginning, since it may change how your code is structured, especially with nested try...catch
.
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.
Since MyError is a class, you can inherit from it too!
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 await
ing.
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?