Reputation: 324
So I want to know how to make sure that my Node application will crash if it comes upon a programmer error(undefined variable, reference error, syntax error...). However, if I am using promise chains then the final catch()
will catch all possible errors including programmer errors.
For example:
PromiseA()
.then((result) => {
foo.bar(); //UNDEFINED FUNCTION HERE!!!!!
return PromiseB(result);
})
.catch(
//handle errors here
)
Now the catch()
statement will also catch the really bad error of an undefined function and then try to handle it. I need a way for my program to crash when it comes up against errors like these.
EDIT: I also just realized that even if I throw an error in the last catch it will just be consumed by the promise chain :-[. How am I supposed to deal with that?
Upvotes: 0
Views: 227
Reputation: 4057
Disclaimer: Below is a description what we do at the company I work. The package linked is written by us.
What we do is to catch all errors and sort them into programmer and operational errors.
We've made small library to help us: https://www.npmjs.com/package/oops-error
For promise chains we use:
import { programmerErrorHandler } from 'oops-error'
...
export const doSomething = (params) => {
somePromiseFunction().catch(programmerErrorHandler('failed to do something', {params}))
}
It marks the error as programmer error, adds 'failed to do something' as error message and adds the params as a context (for debugging later)
For errors that we know that can come up (person not found, validEmail, etc) we do something like
import { Oops } from 'oops-error'
export const sendEmail = (email) => {
if(!isValidEmail(email)) {
throw new Oops({
message: 'invalid email',
category: 'OperationalError',
context: {
email,
},
})
}
...
}
At every level we show the error messages of Operational Errors. So a simple
.cath(e => {
if (e.category == 'OperationalError') {
// handle the gracefully
}
else {
throw e // We will tackle this later
}
}
And at the end of our request in express we have our final error handler, where catch the error, check if its operational and then show the error message, but not the actual context. If its a programmer error we stop the process (not ideal, but we don't want the user to keep messing with broken code)
Upvotes: 1
Reputation: 14423
Basically, what you want to do is to handle those errors that you can potentially recover from. These errors are usually something you throw in your code. For example, if an item is not found in a DB some libraries will throw an Error
. They'll add a type
property or some other property to differentiate the different type of errors.
You can also potentially subclass the Error
class and use instanceof
to differentiate each error.
class myOwnError extends Error {}
Then:
Prom.catch(err => {
if(err instanceof myOwnError){ /* handle error here */ }
else { throw err; }
});
If you want to avoid if/chains, you can use a switch
on error.constructor
:
switch(err.constructor){
case myOwnError:
break;
case someOtherError:
break;
default:
throw err;
}
You can also use an a Map
or regular objects by creating functions for each possible error and storing them. With a Map
:
let m = new Map();
m.set(myOWnError, function(e){ /*handle error here*/ });
m.set(myOtherError, function(e){ /*handle other error here*/ });
Then just do:
Prom.catch(err => {
let fn = m.get(err.constructor);
if(fn){ return fn(err); }
else { throw err; }
});
Upvotes: 1