9. Errors and exceptions

JavaScript does not have a very sophisticated exception-handling system. However, it does provide the [throw] statement, which allows you to signal an error, as well as the try/catch/finally structure, which allows you to catch those errors.
9.1. script [excep-01]
In the following script, we will display the current date in the format [hours:minutes:seconds:milliseconds]. To do this, we will use a JavaScript library called [moment.js]. We install it, as usual, using the [npm] tool:

The script code is as follows:
'use strict';
// moment package
import moment from 'moment';
...
To understand how to write the [import] line on line 4, we can look at the definition of the [moment] module:

- in [1-2], we go to the module definition;
- in [3], we have a TypeScript file, not a JavaScript file. At runtime, this TypeScript file is compiled into a JavaScript file before being used;
- in [4], we search for the [export] statements (Ctrl-F);
- in [5], the statement exports the [moment] object. This can be imported in ES6 as follows:
import moment from 'moment';
You can use any name to import the [moment] object, for example:
import m from 'moment';
Let’s return to the script code:
'use strict';
// moment package
import moment from 'moment';
// try / catch / finally structure
for (let i = 0; i < 10; i++) {
// current date and time
const now = Date.now();
// Format the time to include milliseconds
const time = moment(now).format("HH:mm:ss:SSS");
// the milliseconds
const milli = Number(time.substr(time.length - 3));
// display
console.log("--------------------Iteration # ", i, "at", time);
try {
// number varies depending on the current time
const count = milli % 2;
if (count === 0) {
// display an error message
throw "error";
}
// if we get here, it means there was no error
console.log("No errors");
} catch (error) {
// if we get here, it means there was an error
console.log("error1=", error);
} finally {
// executed in all cases, whether there is an error or not
console.log("finally")
}
}
Comments
- line 4: import the [moment] library;
- The script loops 10 times (line 7). On each loop iteration, the current time is retrieved in the format [hours:minutes:seconds:milliseconds] (lines 8–13);
- if the number of milliseconds is even, an error message is displayed (lines 19–22);
- The goal here is to understand how try / catch / finally works
Execution
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-01.js"
--------------------Iteration #0 at 17:57:04:440
error1= error
finally
--------------------Iteration #1 at 17:57:04:447
no error
finally
--------------------Iteration #2 at 17:57:04:448
error1 = error
finally
--------------------Iteration #3 at 17:57:04:448
error1 = error
finally
--------------------Iteration #4 at 17:57:04:448
error1 = error
finally
--------------------Iteration #5 at 17:57:04:448
error1 = error
finally
--------------------Iteration #6 at 17:57:04:448
error1 = error
finally
--------------------Iteration #7 at 17:57:04:448
error1 = error
finally
--------------------Iteration #8 at 17:57:04:449
no error
finally
--------------------Iteration #9 at 17:57:04:449
no error
finally
We can see that the [finally] clause is always executed, whether there is an error or not.
9.2. script [excep-02]
This script demonstrates that the [throw] statement can throw any type of data and that this data is fully captured by the [catch] clause.
'use strict';
// you can "throw" just about anything to signal an error
let i = 0;
console.log("--------------------test # ", i);
// throw a string
try {
throw "error message";
} catch (error) {
// An error occurred
console.log("error=[", error, "], type=", typeof (error));
}
// increment an array
i++;
console.log("--------------------test # ", i);
try {
throw [1, 2, 3]
} catch (error) {
// An error occurred
console.log("error=[", error, "], type=", typeof (error));
}
// cast a literal object
i++;
console.log("--------------------test # ", i);
try {
throw { name: "Hercules", country: "Ancient Greece" }
} catch (error) {
// An error occurred
console.log("error=[", error, "], type=", typeof (error));
}
// throw an Error
i++;
console.log("--------------------test # ", i);
try {
throw new Error("network connection error");
} catch (error) {
// An error occurred
console.log("error=[", error, "], type=", typeof (error));
}
// throw an Error object
i++;
console.log("--------------------test # ", i);
try {
throw new Error("network connection error");
} catch (error) {
// An error occurred - the message is in [error.message]
console.log("error.message=[", error.message, "], type(error)=", typeof (error));
}
Comments
- lines 35, 44: [Error] is a JavaScript class whose constructor accepts an error message as an optional first parameter. This message can be retrieved from the [Error.message] property (line 47);
- There are other classes besides [Error] that can signal an error: [EvalError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError);
Execution
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js"
--------------------test #0
error=[ error message ], type= string
--------------------test #1
error = [ [ 1, 2, 3 ] ], type = object
--------------------test #2
error=[ { name: 'hercule', country: 'ancient greece' } ], type= object
--------------------test #3
error=[ Error: network connection error
at Object.<anonymous> (c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js:35:9)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:251206)
at c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245054
at Generator.next (<anonymous>)
at bl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245412)
at kl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:247659)
at Object.u (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287740)
at Object.o (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287137)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:284879)
at Object.apply (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:199341) ], type= object
--------------------test #4
error.message=[ network connection error ], type(error)= object
9.3. script [excep-03]
This script demonstrates that, within a [catch], you can distinguish the type of [Error] instance intercepted by the [catch]:
'use strict';
// moment package
import moment from 'moment';
// distinguish the Error instance received in a [catch]
for (let i = 0; i < 10; i++) {
// current date and time
const now = Date.now();
// format the time to include milliseconds
const time = moment(now).format("HH:mm:ss:SSS");
// the milliseconds
const milli = Number(time.substr(time.length - 3));
console.log("--------------------iteration # ", i);
try {
// number [0, 1, 2]
const num = milli % 3;
switch (number) {
case 0:
throw new ReferenceError("error 1");
case 1:
throw new RangeError("error 2");
default:
throw new EvalError("error 3");
}
} catch (error) {
// An error occurred
if (error instanceof ReferenceError) {
console.log("ReferenceError:", error.message);
} else {
if (error instanceof RangeError) {
console.log("RangeError:", error.message);
}
else {
if (error instanceof EvalError) {
console.log("EvalError:", error.message);
}
}
}
}
}
Execution
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-03.js"
--------------------Iteration #0
ReferenceError: error 1
--------------------Iteration #1
RangeError: error 2
--------------------Iteration #2
RangeError: error 2
--------------------Iteration #3
RangeError: error 2
--------------------iteration #4
RangeError: error 2
--------------------iteration #5
RangeError: error 2
--------------------iteration #6
EvalError: error 3
--------------------iteration #7
EvalError: error 3
--------------------iteration #8
EvalError: error 3
--------------------iteration #9
EvalError: error 3