【问题标题】:returned express err object doesn't contain err.message返回的 express err 对象不包含 err.message
【发布时间】:2016-05-20 13:11:17
【问题描述】:

我问了另一个与错误有关的问题。不确定我是否应该编辑该问题。

无论如何,对于以下代码:

app.use((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
    message: err.message,
    err // this err object doens't have err.message property
  });
  next();
});

我不明白这是 Node 的事情还是 Express 的事情。

有人能解释一下这是怎么发生的吗?

err 对象返回时不应该包含其所有属性吗?

目前我正在这样做以解决它:

res.json({
  err: Object.assign(err, { message: err.message })
});

【问题讨论】:

    标签: javascript node.js express ecmascript-6


    【解决方案1】:

    err 对象返回时不应该包含其所有属性吗?

    对于大多数 JSON 序列化程序,这将完全取决于属性是否可枚举

    在规范中,Error 对象的message 属性is defined as non-enumerable,因此它不会出现在 JSON 中。

    听到您的 assign 方法有效,我感到很惊讶,因为根据规范,它应该只写回现有属性,该属性是不可枚举的,并且将保持不变。这就是 V8 在 Chrome 50 中所做的:

    var err = new Error("the error");
    console.log("err.message is enumerable? " + getPropDesc(err, "message").enumerable);
    var obj = Object.assign(err, {message: "updated"});
    console.log("obj === err? " + (obj === err)); // should be true
    console.log("obj.message is enumerable? " + getPropDesc(obj, "message").enumerable);
    console.log("JSON for err: " + JSON.stringify(err));
    if (obj !== err) { // shouldn't be true
      console.log("JSON for obj: " + JSON.stringify(obj));
    }
    
    function getPropDesc(o, prop) {
      var desc;
      while (o) {
        desc = Object.getOwnPropertyDescriptor(o, prop);
        if (desc) {
          return desc;
        }
        o = Object.getPrototypeOf(o);
      }
      return null;
    }

    我希望 this 能够工作:

    res.json({
      err: Object.assign({}, err, { message: err.message })
      // Note -----------^^^^
    });
    

    ...但不是您引用的内容。也许您得到的 err 对象不是 Error 实例。 Error(在 ES5 及更早版本中)是出了名的难以子类化,因此很可能您使用的代码没有尝试这样做,而是执行以下操作:

    var err = Object.create(new Error("the error"));
    

    会导致您看到的行为:

    var err = Object.create(new Error("the error"));
    console.log("err.message is enumerable? " + getPropDesc(err, "message").enumerable);
    var obj = Object.assign(err, {message: "updated"});
    console.log("obj === err? " + (obj === err)); // should be true
    console.log("obj.message is enumerable? " + getPropDesc(obj, "message").enumerable);
    console.log("JSON for err: " + JSON.stringify(err));
    if (obj !== err) { // shouldn't be true
      console.log("JSON for obj: " + JSON.stringify(obj));
    }
    
    function getPropDesc(o, prop) {
      var desc;
      while (o) {
        desc = Object.getOwnPropertyDescriptor(o, prop);
        if (desc) {
          return desc;
        }
        o = Object.getPrototypeOf(o);
      }
      return null;
    }

    【讨论】:

    • 所以我可以得出结论,当您执行const err = new Error('errormsg') 时,它会创建具有不可编号err.messageerr 对象,但如果我执行const err = new Error(); err.message="erromsg"err.message 将是可枚举的?
    • @Alex:实际上,Error 对象上的message 属性始终是不可枚举的。我已经用详细信息更新了答案。如果您的 assign 工作正常,这听起来像是您正在使用的 NodeJS 中的 V8 版本中的错误(或者,您获得的 err 对象不是真正的 Error 对象) . Chrome 50 中的 V8 在执行 assign 时不会使 message 可枚举。
    猜你喜欢
    • 2022-10-01
    • 2012-01-14
    • 2011-03-28
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2011-10-12
    • 2021-02-14
    • 2021-01-18
    相关资源
    最近更新 更多