【问题标题】:Error handling in Node JS + Express applicationNode JS + Express 应用程序中的错误处理
【发布时间】:2017-12-11 07:33:23
【问题描述】:

我正在使用 Node JS(8.4.0 版)、Express(4.15.3 版)和 Passport(0.3.2 版)编写一个小型 Web 应用程序进行身份验证。

我正在使用 PostgreSQL 9.6 作为数据库。

我无法理解如何在我的应用程序中使用 Promise 来处理错误。

我已将我的应用分为路由(包含与通过 http 请求处理哪些路由相关的信息)、视图(用于呈现页面的把手模板)和模型(与数据库查询相关的功能)。

这是来自模型的示例代码:

var helpers = require('./helpers'); //Has a function to perform db queries

exports.getCustomerDetails = (cust_id,cb)=>{

    var qs = 'select * FROM customers WHERE cust_id=($1)';
    var params = [cust_id];

    helpers.dbquery(qs,params,(error,results)=>{

        if(error){
            return cb(error);
        }

        return cb(null,results);

    });

}

目前,我在相应的路由处理程序中所做的是发送HTTP 500作为响应。

//Get Customer details based on cust_code as input

router.get('/getCustomerDetails',(req,res,next)=> {
    if (req.user) {

      var cust_code = req.query.value;

      db.getCustomerDetails(cust_code, (error, result) => {

        if (error) {
          res.sendStatus(500);
        }
        res.status(200).send(result);
      });
    } else {
      res.sendStatus(401);
    }
})

我想了解在两个级别(即路由和数据库)处理错误的最佳方法是什么。

我阅读了几篇关于错误处理的文章并搜索了 Stackoverflow,但作为任何类型开发的初学者,我无法完全理解它。

请建议如何处理我的网络应用程序中的错误以及任何可以帮助我理解网络应用程序中的错误处理的参考资料。

【问题讨论】:

  • 数据库应该将错误返回给路由。如果路由返回错误,则应发送适当的错误状态作为响应。而且,您的代码应该为每个请求发送一个且仅一个响应(您上面的一条路由尝试发送多个响应)。仅供参考,对所有异步操作使用承诺而不是普通回调将使错误传播回路由变得非常、非常、非常简单,特别是当给定路由涉及多个异步操作时。
  • 抱歉,如果代码不够清晰。如果没有有效的用户凭据来访问路由,则会发送 401 响应。所以只发送了一个响应。我将探索在我的项目中使用 Promise 的选项。非常感谢:)

标签: javascript node.js postgresql express


【解决方案1】:

以下内容可以满足您的要求。创建一个 Promise,捕获该 Promise 的拒绝并返回您创建的 Promise,但不使用 catch,以便调用者可以再次捕获拒绝。

var helpers = require('./helpers'); //Has a function to perform db queries

exports.getCustomerDetails = (cust_id, cb) => {
  var qs = 'select * FROM customers WHERE cust_id=($1)';
  var params = [cust_id];
  //create a promise
  const p = new Promise(
    (resolve,reject) =>
      helpers.dbquery(qs, params, (error, results) =>
        (error)
          ? reject(error)
          : resolve(results)
      )
  );
  //catch the reject
  p.catch(
    error => {
      //... do something with the error on the db level
    }
  );
  //return the promise that DID NOT have the error caught
  return p;
};


router.get('/getCustomerDetails',(req,res,next)=> {
  if (req.user) {
    var cust_code = req.query.value;
    //getCustomerDetails returns a promise
    db.getCustomerDetails(cust_code)
    .then(
      result =>
        res.status(200).send(result)
    )
    .catch(
      error =>
      res.sendStatus(500)
    )
  } else {
    res.sendStatus(401);
  }
});

【讨论】:

  • 非常感谢您的解释。我对下面的代码 sn-p 的行为有疑问。当我说“return p”时,错误是传播给调用者还是发送给调用者的数据库查询结果?我问这个是因为我不确定是否可以在数据库级别处理错误。
  • @UmashankarVarma 是的,您可以在 cmets 中清楚地看到。如果出现问题,数据库函数和快速请求处理程序都会收到错误。您如何处理错误取决于您。
【解决方案2】:

在我看来,最好的方法是处理路由层中的所有错误,以便根据接口正确格式化它们。想象一下,将来您通过 GraphQL 层更改您的 REST API 层,使用这种方法您只需要修改该层,而不是其余的。 从其他层抛出所有错误的方法:我通常创建一个Error对象并添加几个自定义属性,例如:

var error = Error();
error.code = 401;
error.log = true;
error. translate = true;
error.message = "Unauthorized";
....
throw error;

在路由层,您可以捕获错误并使用所有数据创建自定义响应。它灵活而强大。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2018-03-10
    • 2012-05-24
    • 2016-04-07
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 2014-02-04
    相关资源
    最近更新 更多