Js Error Handling
A better programmer best friend is “Error”. It may occur because of our mistakes, and unexpected user input. But we can catch the error by applying.
The “try…cath” syntax:
try{//code} catch(err){//error handling}
It works like this:
- First, the code in
try {...}
is executed. - If there were no errors, then
catch (err)
is ignored: the execution reaches the end oftry
and goes on, skippingcatch
. - If an error occurs, then the
try
execution is stopped, and control flows to the beginning ofcatch (err)
. Theerr
variable (we can use any name for it) will contain an error object with details about what happened.
try...catch
only works for runtime errors
For try...catch
to work, the code must be runnable. In other words, it should be valid JavaScript.
It won’t work if the code is syntactically wrong, for instance, it has unmatched curly braces:
try { {{{{{{{{{{{{
}catch (err) {
alert("Hi! i cannot understand the code.");
}
try...catch
can only handle errors that work only in invalid code. Such errors are called “runtime errors” or, sometimes, “exceptions”.
*try...catch
works synchronously
If an exception happens in the “scheduled” code, like in setTimeout
, then try...catch
won’t catch it:
Code: setTimeout(function() {
try {
noSuchVariable; // try…catch handles the error!
} catch {
alert( “error is caught here!” );
}
}, 1000);
Error object
When an error occurs, JavaScript generates an object containing the details about it. The object is then passed as an argument to catch
:
try { // ...
} catch (err) {
// <-- the "error object", could use another word instead of err // ...
}
For all built-in errors, the error object has two main properties:
name
Error name. For instance, for an undefined variable that’s "ReferenceError"
.message
Textual message about error details.
There are other non-standard properties available in most environments. One of most widely used and supported is:
stack
Current call stack: a string with information about the sequence of nested calls that led to the error. Used for debugging purposes.
try...catch
.
As we already know, JavaScript supports the JSON.parse(str) method to read JSON-encoded values.
Usually it’s used to decode data received over the network, from the server or another source.
We receive it and call JSON.parse
like this:
let json = '{"name":"John", "age": 30}'; // data from the serverlet user = JSON.parse(json); // convert the text representation to JS object// now user is an object with properties from the string
alert( user.name ); // John
alert( user.age ); // 30
Throwing our own errors
What if json
is syntactically correct, but doesn’t have a required name
property?
Like this:
let json = '{ "age": 30 }'; // incomplete datatry { let user = JSON.parse(json); // <-- no errors
alert( user.name ); // no name!} catch (err) {
alert( "doesn't execute" );
}
“Throw” operator
The throw
the operator generates an error.
The syntax is:
throw <error object>
JavaScript has many built-in constructors for standard errors: Error
, SyntaxError
, ReferenceError
, TypeError
and others. We can use them to create error objects as well.
Their syntax is:
let error = new Error(message);
// or
let error = new SyntaxError(message);
let error = new ReferenceError(message);
// ...
Rethrowing
In the example above we use try...catch
to handle incorrect data. But is it possible that another unexpected error occurs within the try {...}
block? Like a programming error (variable is not defined) or something else, not just this “incorrect data” thing.
For example:
let json = '{ "age": 30 }'; // incomplete datatry {
user = JSON.parse(json); // <-- forgot to put "let" before user // ...
} catch (err) {
alert("JSON Error: " + err); // JSON Error: ReferenceError: user is not defined
// (no JSON Error actually)
}
try…catch…finally
Wait, that’s not all.
The try...catch
the construct may have one more code clause: finally
.
If it exists, it runs in all cases:
- after
try
, if there were no errors, - after
catch
, if there were errors.
The extended syntax looks like this:
try {
... try to execute the code ...
} catch (err) {
... handle errors ...
} finally {
... execute always ...
}
finally
and return
The finally
clause works for any exit from try...catch
. That includes an explicit return
.
In the example below, there’s a return
in try
. In this case, finally
is executed just before the control returns to the outer code.
function func() { try {
return 1; } catch (err) {
/* ... */
} finally {
alert( 'finally' );
}
}alert( func() ); // first works alert from finally, and then this one
Global catch
Environment-specific
The information from this section is not a part of the core JavaScript.
Let’s imagine we’ve got a fatal error outside of try...catch
, and the script died. Like a programming error or some other terrible thing.
Is there a way to react to such occurrences? We may want to log the error, show something to the user (normally they don’t see error messages), etc.
There is none in the specification, but environments usually provide it, because it’s really useful. For instance, Node.js has process.on("uncaughtException")
for that. And in the browser, we can assign a function to the special window.onerror property, that will run in case of an uncaught error.
The syntax:
window.onerror = function(message, url, line, col, error) {
// ...
};
message
Error message.url
URL of the script where the error happened.line
, col
Line and column numbers where error happened.error
Error object.