如何区分承诺链中的操作错误和程序员错误?

时间:2018-08-22 22:31:21

标签: javascript node.js es6-promise

因此,我想知道如何确定如果遇到程序员错误(未定义变量,引用错误,语法错误...),我的Node应用程序将崩溃。但是,如果我使用的是Promise链,那么最后的catch()将捕获所有可能的错误,包括程序员错误。

例如:

PromiseA()
.then((result) => {
        foo.bar(); //UNDEFINED FUNCTION HERE!!!!!
        return PromiseB(result);
        })
.catch(
//handle errors here
)

现在,catch()语句还将捕获未定义函数的真正严重错误,然后尝试对其进行处理。当遇到此类错误时,我需要一种使程序崩溃的方法。

编辑:我也刚刚意识到,即使我在最后一个catch中抛出一个错误,它也会被promise链消耗:-[。我应该如何处理?

2 个答案:

答案 0 :(得分:1)

基本上,您要做的是处理可能会从中恢复的那些错误。这些错误通常是您在代码中抛出的错误。例如,如果在数据库中找不到某个项目,则某些库将抛出Error。他们会添加一个type属性或其他属性来区分不同类型的错误。

您还可以潜在地将Error类子类化,并使用instanceof来区分每个错误。

 class myOwnError extends Error {}

然后:

Prom.catch(err => {
   if(err instanceof myOwnError){ /* handle error here */ }
   else { throw err; }
});

如果要避免if / chains,可以在switch上使用error.constructor

switch(err.constructor){
    case myOwnError:
    break;
    case someOtherError:
    break;
    default:
      throw err;
}

您还可以通过为每个可能的错误创建函数并将其存储来使用Map或常规对象。使用Map

let m = new Map();
m.set(myOWnError, function(e){ /*handle error here*/ });
m.set(myOtherError, function(e){ /*handle other error here*/ });

然后就做:

Prom.catch(err => {
   let fn = m.get(err.constructor);
   if(fn){ return fn(err); }
   else { throw err; }
});

答案 1 :(得分:1)

免责声明:以下是我们在我工作的公司所做的描述。链接的程序包是由我们编写的。

我们要做的是捕捉所有错误并将它们分类为程序员和操作错误。

我们已经建立了小型图书馆来帮助我们:https://www.npmjs.com/package/oops-error

对于诺言链,我们使用:

import { programmerErrorHandler } from 'oops-error'

...
export const doSomething = (params) => {
    somePromiseFunction().catch(programmerErrorHandler('failed to do something', {params}))
}

将错误标记为程序员错误,将“无法做某事”添加为错误消息,并将参数作为上下文添加(供以后调试)

对于我们知道可能会出现的错误(找不到人,validEmail等),我们执行类似的操作

import { Oops } from 'oops-error'

export const sendEmail = (email) => {
    if(!isValidEmail(email)) {
        throw new Oops({
            message: 'invalid email',
            category: 'OperationalError',
            context: {
                email,
            },
        })
    }
    ...
}

在每个级别,我们都显示操作错误的错误消息。很简单

.cath(e => {
  if (e.category == 'OperationalError') {
    // handle the gracefully
  }
  else {
    throw e // We will tackle this later
  }
}

在express的请求结尾处,我们有最终的错误处理程序,可以捕获错误,检查其是否可操作,然后显示错误消息,但不显示实际上下文。如果是程序员错误,我们将停止该过程(这不理想,但是我们不希望用户继续弄乱已损坏的代码)