【问题标题】:RestFul Api Node.js & Mongoose: handling errorsRestFul Api Node.js 和 Mongoose:处理错误
【发布时间】:2013-11-30 00:59:20
【问题描述】:

我想用 Node.js、Express、MongoDB 和 Mongoose 创建一个宁静的 API。

架构、模型和路由如下:

// Schema
var OperatorSchema = new Schema({
    name : { type: String, unique: true , required: true},
    short_name : { type: String, unique:true, required: true },
});
Operator = mongoose.model('Operator', OperatorSchema);

// My Api for Operator
app.post('/api/operators', common.createOperator);
exports.createOperator = function(req, res){
    Operator.create(req.body, function (err, operator) {
        // If failed, return error message
        if (err) {
            console.log(err);
            res.send(404, err)
        }
        else {
            res.send(operator)
        }
    })
};

我有三个问题:

1 - 处理类似的错误我发现传递给回调的 err 对象具有不同的结构,具体取决于错误来自 mongoose 还是 mongo。

// Mongo Error:
{
    "name": "MongoError",
    "err": "E11000 duplicate key error index: ussdauto.operators.$name_1  dup key: { : \"OpTest\" }",
    "code": 11000,
    "n": 0,
    "connectionId": 231,
    "ok": 1
}

// Mongoose Error:
{
    "message": "Validation failed",
    "name": "ValidationError",
    "errors": {
    "short_name": {
        "message": "Path `short_name` is required.",
        "name": "ValidatorError",
        "path": "short_name",
        "type": "required"
      }
    }
}

我不想暴露关于错误的所有细节:只需要一条解释错误的消息就足够了,例如,不需要知道它是 mongoerror 还是 validationError。你是怎么管理的?

2 - 第二个问题更加全球化:我将有多个 API,每次我都需要做同样的工作:检查是否有错误,是否有一些通过 API 返回JSON 错误消息,如果没有正常继续。如何只使用一个函数来处理错误并在任何地方使用它?

3 - 我来自 python 世界(实际上是 Django),Tastypie 是一个非常棒的模块,它自己处理所有这些东西。你知道 Node.js + Express 是否存在这样的模块吗?

【问题讨论】:

  • 每个帖子只问一个问题会更好。

标签: node.js mongodb express mongoose


【解决方案1】:

您可以使用名为 processMongooseError(err) 的函数创建一个 Utils 模块(或者真的如您所愿)。然后你可以在函数中做一个简单的检查来确定它是什么类型的错误,然后返回一个简单的错误消息。我在下面提供了一个我正在谈论的示例。

module.exports.processMongooseError = function(err) {
    if(err.name == "MongoError") {
        // mongo db error

    } else if(err.name == "ValidationError") {
        // mongoose error

    }
}

您可以在任何需要的地方都需要此模块,并且应该可以解决您的第二个问题。

【讨论】:

    【解决方案2】:

    如果这仍然是一个问题,我遇到了同样的问题,并使用这个猫鼬插件使错误消息更加一致。 https://www.npmjs.com/package/mongoose-beautiful-unique-validation

    插件将接受 mongodb 错误并将它们转换为类似 mongoose 的错误。

    【讨论】:

      【解决方案3】:

      如果您不想在向 MongoDB 发出 POST 请求后显示完整的错误响应,您可以使用 Promise 作为模型来链接响应并向 RESTFull API 的用户显示自定义内容到 json 响应。

      我会给你一个例子,作为构建 API 时的一个很好的指导:

      1# Schema 模型./api/models/operator

      const mongoose = require('mongoose');
      
      const OperatorSchema = new Schema({
          name : { type: String, unique: true , required: true},
          short_name : { type: String, unique:true, required: true },
      });
      
      module.exports = mongoose.model('Operator', OperatorSchema);
      

      2# Operator CRUD 文件,(POST) 进程./api/routes/operator

      // let's imagine that at this point you have already set up your form somewhere in your app and you are using body-parser, you have some Headers configuration for this route.
      
      
      //import the libraries to execute your CRUD
      
      const express = require('express');
      const router = express.Router();
      const mongoose = require('mongoose');
      const bodyParser = require('body-parser');//generates json structure from incoming form post
      app.use(bodyParser.urlencoded({extended: false}));
      app.use(bodyParser.json());
      
      const Operators = require('../api/models/operators');
      
      router.post('/api/operators', (req, res, next) => {
      
          const operator = new Operator({
              _id: new mongoose.Types.ObjectId(),
              name: req.body.name, //get the form field of "operator" using body-parser
              short_name: req.body.short_name // other fiels... from the Schema model
          }); // Build an object to store to the database using the schema set up
      
          // The following chain method returns a promise which you can build your custom responses for this post,
          // This chain method can be used for POST GET and DELETE requests 
      
          operator.save().then(result => {
              res.status(201).json({
                  message: "Operator Created", //
                  result: result // the "result" object can be filtered or you can simply return the message
              });
      
              // THE RESULT OBJECT PROPERTIES YOU CAN FILTER ON RETURN
              //  "result" : {
              //      name: "some operator name",
              //      short_name: "short guy",
              //      __v : 0,
              //      _id : "mongodb-id-generated"
              // }
      
          }).catch(err => {
              console.log(err);
              res.status(500).json({
                  error: err 
              });
          });
      
      }); // #### POSTS NEW OPERATORS
      

      我使用这个过程已经有一段时间了,它允许开发人员将内容发布到 API 非常有效,如果他们遇到错误,我会向他们展示什么是必要的,以便他们更好地阐述他们的请求。

      【讨论】:

        【解决方案4】:
        "short_name": {
                "message": "Path `short_name` is required.",
        

        此错误是因为,在您的架构中,此字段是必需的

        var OperatorSchema = new Schema({
            name : { type: String, unique: true , required: true},
            short_name : { type: String, unique:true, required: true },
        

        当您没有通过表单或邮递员应用程序提供任何输入时。您不能将必填字段留空。

        我不知道有什么能告诉你什么模块导致错误 但你绝对可以通过查看错误来猜测。

        "name": "MongoError",
            "err": "E11000 duplicate key error
        

        此错误是因为您将名称定义为唯一的,但尝试再次插入相同的名称。

        【讨论】:

          猜你喜欢
          • 2012-08-05
          • 2014-01-07
          • 1970-01-01
          • 2017-06-03
          • 2012-12-28
          • 2021-03-23
          • 2012-04-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多