【问题标题】:How to handle errors between internal server API and HTTP API如何处理内部服务器 API 和 HTTP API 之间的错误
【发布时间】:2014-08-28 13:39:52
【问题描述】:

这就是我的 node.js 服务器的组织方式

问题:API 通过模型(猫鼬)向我的 mongodb 数据库发出请求。所以在 API 层我可以拥有:

User.findById(id, function(user) {
   if(user._id !== userid) return deferred.reject(new Error()); // ??
   if(!user) return deferred.reject(new Error()); // ??
   user[field] = value;
   user.save(function() {
    deferred.resolve(user);
   }); 
});

但是我应该抛出什么错误呢?什么方法会更合适和更用户友好。例如,我可以尝试:

   if(user._id !== userid) return deferred.reject(new Error(403));

但这意味着没有消息,只有错误代码:/

我尝试的另一种解决方案:

exports.errors = errors =

  NOT_FOUND:
    id: "NOT_FOUND"
    code: 404
    message: "Can't found requested object. Please retry"
  UNAUTHORIZED:
    id: "UNAUTHORIZED"
    code: 401
    message: "Please login first"
  FORBIDDEN:
    id: "FORBIDDEN"
    code: 403
    message: "Access denied."
  DATABASE_ERROR:
    id: "DATABASE_ERROR"
    code: 500
    message: "Error with databse. Please retry"

exports.throwError = throwError = (message, id) ->
  if typeof message is "string" then err = new Error message else err = message
  err.type = id
  err.data = errors[id]
  return err

exports.handleHttp = (err, req, res, format="text") ->
  console.log("   Error - #{err.message} (#{err.type}) on #{req.url}".red)
  console.log(err.stack)
  if format is "text"
    res.send err.data.code, "#{err.data.type}: #{err.message}"
  if format is "json"
    res.send err.data.code,
      type: err.data.type
      message: err.message
      id: err.type
      status: "error"
      errors: err.errors

所以我会这样使用它:

   if(user._id !== userid) return deferred.reject(error.throwError("Forbidden", "UNAUTHORIZED"));

在控制器中(在承诺之后)

.fail (err)->
    errors.handleHttp err, req, res, "json"

但我不喜欢这种解决方案,这让我感到苦涩,不满意。还有什么想法吗?

【问题讨论】:

    标签: node.js mongodb express error-handling mongoose


    【解决方案1】:

    您可以定义扩展现有 Error 对象的新 Error 对象。例如,以下是 404 错误:

    function HttpError(message, code) {
        this.message = message || "";
        this.code = code || 500;
    }
    
    HttpError.prototype = Object.create(Error.prototype);
    
    HttpError.prototype.send = function send(req, res) {
        var type = req.accepts("json", "html", "text");
    
        switch(type) {
            case "json":
                res.send(this.code, JSON.stringify(this));
            break;
    
            case "html":
            case "text":
                res.send(this.code, "An error occurred: " + this.message);
            break;
        }
    };
    
    function NotFoundError(message, code) {
        this.name = "NotFound";
        this.message = message || "Could not find the object you were requesting";
        this.code = code || 404;
    }
    NotFoundError.prototype = Object.create(HttpError.prototype);
    

    然后你可以像这样使用它:

    User.findById(id, function(user) {
       if(!user) return deferred.reject(new NotFoundError());
    
       user[field] = value;
       user.save(function() {
        deferred.resolve(user);
       }); 
    });
    

    您可以将所有错误(500、404、401 等)放在错误文件中并将其包含在内。所以很可能是new errors.NotFoundError();

    然后,在您的控制器中,您可以有一个失败回调函数,如下所示:

    getUser().fail(function(err) { err.send(req, res) });
    

    这只有在 err 是 HttpError 类的实例时才有效。

    【讨论】:

    • 看起来很有趣,谢谢!以及如何在控制器上处理?
    • 更新了控制器逻辑。处理它的方式与最初定义它的方式非常相似。
    • 非常感谢!我也许可以在处理 res 的 proto 中添加一个函数?
    • 哦,是的,那会很好用!有一个继承自具有 res 处理程序的 Error 的 HttpError ,并且您的每个错误都继承自 HttpError 类。 :-)
    • 我已更新示例以执行我在评论中概述的内容。
    猜你喜欢
    • 2018-07-08
    • 1970-01-01
    • 2023-01-30
    • 2015-02-14
    • 2014-05-26
    • 1970-01-01
    • 2020-02-19
    • 2016-07-29
    • 2021-09-07
    相关资源
    最近更新 更多