Error Handling in Node.js (meetup notes)
JS
R
JavaScriptNode.js error handling done properly. TLDR: Always use async await and use the latest version of Node.js
1JavaScript Errors
2JavaScript is an asynchronous language, so the stack trace is not so clear as classical languages.
3We have multiple call stacks in a stack trace.
4In JavaScript you can throw anything.
5
6Promise if we fail synchronously the promise rejects automatically.
7
8There is a chance that a Promise may never reject.
9
10> Primitive Errors
11
12Rejecting an Error: contatenating a string with an error is not good.
13
14> Debugging
15
16When testing an application we want to have good coverage.
17We only tend to test good paths
18Test the bad paths also
19
20> Nested Try/Catch
21
22## Patterns
23Create Error Classes
24Class AppplicationErrror extends Error {
25 get name() {
26 return this.constructor.name;
27 }
28}
29
30Class DBError extends AppplicationErrror {};
31
32Class XPTOErrror extends AppplicationErrror {};
33
34module.exports = {
35 DBError,
36 XPTOErrror
37}
38
39Const { userFacingError } = import (‘./base-class’);
40Class BadRequestError extends UserFacingError {
41 construcvtor(msg, options = {}) {
42 super(message);
43 // attach relevant info
44 for(const[key,value] of Object.entries(options)) {
45 this[key] = value;
46 }
47 }
48 get statusCode() {
49 return 400;
50 }
51}
52
53Class NotFoundError extends UserFacingError {
54 constructor() {
55 super();
56 }
57 getStatusCode() {
58 return 400;
59 }
60}
61
62
63The Error Classes
64> Application specific base class
65> Validate input
66> Move individual module
67> Only source of truth
68> Contain all information for users and developers
69
70If an error comes from application error class, we know that it’s ours.
71If it’s not, its unexpected.
72
73
74Error Handling Layers
75
76Express
77Global Handler
78If (err instanceof UserFacingError) {
79 res.sendStatus(err.statusCode)
80 res.status(err.statusCode)
81 log.error(err, req.params, req.user);
82}
83
84Databases
85- Fallback mechanism in case DB call fails
86- Have a Fallback database running (mongodb connects to 2)
87
88await(sleep(delay))
89
90Debugging Utils
91`util.promisify`
92
93Const { promisify } = require(‘util’);
94Const promiseGet = promisify(db.get).bind(db);
95
96await promiseGet(‘foo’);
97
98Unhandled Rejections
99
100node —unhandled-rejections=strict ./unhandled/unhandled.js (throw new Error(‘xpto’)
101
102Use as much async await as you can.
103
104Promise constructor has a dead zone (code can run after promise.resolve doesn’t run)
105
106There are about 15-50 errors per 1000 lines of code
107
108Always wrap JSON.parse() in try catch blocks.
109
110try-catch doesn’t work on async callbacks, unhandled promises or streams.
111Created on 10/12/2019