为什么我的自定义Error对象被Express路由器转换为String?

时间:2013-03-21 20:34:08

标签: node.js express url-routing

我在node.js(0.8.12)中使用express(2.5.8)使用自定义Error对象。发生错误时,我想将它们路由到我的自定义错误处理程序,但我的自定义错误对象将转换为字符串,而本机错误对象保持不变。


这是一个简单的例子:

var express = require('express');

var APIError = function(type) {
    this.type = type;
}
APIError.prototype = new Error();

var app = express.createServer();

app.use(app.router);
app.use(apiErrorHandler);

function log(source, err) {
  console.log(
    source, 
    typeof err, 
    err.constructor.name, 
    err instanceof APIError, 
    err instanceof Error
  );
}

function apiErrorHandler(err, req, res, next) {
  log("error handler:", err);
}

app.get('/', function(req, res, next) {
  var err = new APIError("notAllowed");
  log("router:", err);
  next(err);
});

app.listen(80);

此示例的控制台输出如下:

router: object Error true true
error handler: string String false false

如果我用new APIError("notAllowed")替换new Error("notAllowed"),则保留该对象并且请求产生此输出:

router: object Error false true
error handler: object Error false true

为什么我的自定义Error对象被转换,虽然它是一个错误的实例?

2 个答案:

答案 0 :(得分:3)

实际上发生的事情是显示的字符串根本不是你的错误对象 - 这是另一个错误被抛入Express的内部(“非法访问”异常)。当Express将错误对象与字符串进行比较时,会发生错误。

根本原因显然是在自定义Error对象上设置“type”属性。这显然是V8的禁忌 - 它导致toString()抛出“非法访问”异常。更多详情:https://code.google.com/p/v8/issues/detail?id=2397

答案 1 :(得分:2)

试试这个。请注意,APIError现在是一个命名函数:

var util = require('util');

function APIError(type) {
    Error.call(this, {
        message: type,
        constructorOpt: APIError
    });
    this.name = 'APIError';
}
util.inherits(APIError, Error);
APIError.prototype.name = 'APIError';

另外,看看here