简体   繁体   中英

How to differentiate between operational and programmer errors in promise chains?

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?

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; }
});

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM