Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javascript中处理两层之间的错误_Javascript_Node.js_Error Handling - Fatal编程技术网

在javascript中处理两层之间的错误

在javascript中处理两层之间的错误,javascript,node.js,error-handling,Javascript,Node.js,Error Handling,我有一个使用express和3层(控制器、api和模型)的node.js应用程序 控制器要求API层发布、编辑或添加对象(promise样式)。API验证并执行请求(使用模型层(mongoose))。控制器必须通过呈现错误页面或闪存消息来告知客户端是否已接受其请求。 这是一张显示主要结构的小图表 下面是一个例子: Controller: exports.doEdit = function(req, res) { var args; args = req.body;

我有一个使用express和3层(控制器、api和模型)的node.js应用程序

控制器要求API层发布、编辑或添加对象(promise样式)。API验证并执行请求(使用模型层(mongoose))。控制器必须通过呈现错误页面或闪存消息来告知客户端是否已接受其请求。 这是一张显示主要结构的小图表

下面是一个例子:

Controller:

  exports.doEdit = function(req, res) {
    var args;
    args = req.body;
    return app.api.mods.edit(req.getUserId(), req.params.id, args.name, args.value).then(function(status) {
      return res.send(200, "Saved!");
    }).fail(function(err) {
      return res.send(400, err.message);
    });
  };

API Layer:

/*
  Edit a mod
  @param userid the current logged user id 
  @param slug the slug of the mod
  @param field the field to be edited
  @param value the new value
  @permission mod:edit
  */


  exports.edit = (function(userid, slug, field, value, callback) {
    return canThis(userid, "mod", "browse").then(function(can) {
      var Mod;
      Mod = mongoose.model("Mod");
      return Mod.findOne({
        slug: slug
      }, function(err, mod) {
        if (can === false && mod._id !== userid) {
          return callback(new Error("unauthorized"));
        }
        if (err || !mod) {
          if (err) {
            console.log(err);
          }
          return callback(new Error("Please try again"));
        }
        mod[field] = value;
        mod.save();
        return callback("ok");
      });
    });
  }).toPromise(this);
如何对错误进行简单、灵活和清晰的沟通?

我想添加一个类似这样的JSON对象

{
    status: "error",
    code: "404",
    id: "not_found",
    message: "Not found"
}
但如何将其添加到只接收一条消息的错误中?它是否灵活且“干净”?


整个项目都可以在这里看到:

如果我没弄错的话,你是在问如何用足够的信息将错误传播给客户

首先,javascript是动态的,因此您可以在将错误实例传递给回调/响应之前,将所需的属性添加到错误实例中

    if (can === false && mod._id !== userid) {
      var error = new Error("unauthorized")
      error.code = 401
      error.id = "not_authorized"
      return callback(error);
    }
不要忘记,在分离关注点的问题上,每一层都有自己的语义,它必须封装较低的层。错误处理也是如此。有时让错误冒泡出来是合适的,但在大多数情况下这是不好的,或者至少是不好的用户体验。因此,至少在控制器中,您应该将此处冒泡的任何错误转换为用户/客户端友好的http错误代码。为此,您必须考虑错误对上下一层意味着什么

所以像
res.send(404,err.message)
这样的代码很简单,但不是很有用。如果你真的想做一个好的错误处理,那么你必须再做一步,在这里做一些匹配。在像Java这样的静态类型语言中,您可以进行类型匹配。对于JS,这也是可能的(使用instanceof),但这不是很可靠。但是,您可以使用其他所有属性,或者使用定义良好的错误类型引入自己的属性

    var error = new Error("Some lengthy message for humans, who are reading log files")
    error.errType = require('./errorTypes').NOT_AUTORIZED
    callback(error)
在api用户代码中

    if(err){
        if(err.errType === errorTypes.NOT_AUTHORIZED)
           return res.send(401, "Wrong credentials")        
    }
为了减少代码重复,您可以将错误匹配提取到自己的模块或简单函数中,将内部类型映射到外部类型

因此,这很简单(与easy不同,easy取决于您的上下文),从回调风格代码的意义上讲,它是干净的。这同样适用于基于承诺的API,只有在这里,您才有错误传播和解析与拒绝控制流的分离


我没有介绍Node.js域(因为它们不容易与express一起使用)和Zone.js之类的内容。这可能会为错误处理带来另一个工具链,但本质上还是一样的。您必须在某个地方转换错误。

非常感谢。我想知道,扩展类错误来创建我自己的类型怎么样?这有一个怪癖,导致扩展错误的自定义错误无法捕获stattrace。也许可以澄清这一点。邪恶的黑客攻击是可能的,但我怀疑它的价值,因为你不能在js中尝试/捕获错误类型,而且你必须自己反省错误。这是一种交易:subcass+
实例的
或自定义属性+
==