3

我正在开发一个 Node.js/CoffeeScript 应用程序,我在其中使用类层次结构来解决错误。当我throw在路由处理程序的根目录中使用语句时,一切都很好:

class APIError extends Error
    constructor: ->

app.error (err, req, res, next) ->
    if err instance of APIError
       console.log 'APIError captured'

app.get '/', (req, res, next) ->
    throw new APIError

但是,对于 Mongoose,使用throw回调函数中的语句:

app.get '/', (req, res, next) ->
    UserModel.where('name', 'Joe').findOne (err, doc) ->
        throw new APIError

结果是

/usr/local/lib/node_modules/mongoose/lib/utils.js:413
    throw err;
          ^
Error: 

当我打电话时next(),如

app.get '/', (req, res, next) ->
    UserModel.where('name', 'Joe').findOne (err, doc) ->
        return next new APIError

甚至在处理程序的主体中使用它:

app.get '/', (req, res, next) ->
    next new APIError

undefined在控制台中被打印出来。

将最后一条语句更改为return next Error按预期工作,即在控制台中打印出异常堆栈跟踪:

app.get '/', (req, res, next) ->
    return next Error 'This works as expected'

是 Node.js 问题还是我在 CoffeeScript 中定义类的方式?任何想法如何使这种错误层次结构起作用?

更新 1

我可以确认这是 CoffeeScript 类的实现方式。使用标准的 JS 原型链定义可以解决问题,但感觉不对。

4

3 回答 3

2

在其构造函数中设置name类的属性可以解决问题(第 3 行):

class APIError extends Error
    constructor: ->
        @name = 'APIError'

app.use (err, req, res, next) ->
    if err instance of APIError
        console.log 'Error captured'

app.get '/', (req, res, next) ->
    #This will work: captured by error handler
    throw new APIError

app.get '/in-mongoose-callback', (req, res, next) ->
    UserModel.where('name', 'Joe').findOne (err, doc) ->
        #This one works as expected: captured by error handler
        return next new APIError

这是由于CoffeeScript 1.3.3(2012 年 5 月 15 日)中的一项更改:

由于 JavaScript 严格模式的新语义,CoffeeScript 不再保证构造函数在所有运行时都有名称。参见#2052 进行讨论。

请注意,使用throw语句而不是next()在 Mongoose 查询回调中将不起作用

于 2012-07-26T14:16:52.980 回答
1

在使用 express 时,我扩展了 Error,将名称设置为原型属性,并执行堆栈跟踪。

class RequestError extends Error
    name: 'RequestError'
    constructor:(@status, message)->
        super message
        Error.captureStackTrace @, @constructor

我可以new RequestError 403, 'Invalid username/password.'为错误的用户登录或new RequestError 404, 'Page not found.'错误的页面请求做。当我发现错误时

require 'colors'
console.error error.stack.red  # logs where any error occured
if error instanceof RequestError
    # proper response for user errors
    response.status(error.status).send(error.message)
else response.status(500).send('Internal Server Error') # for 'other' errors the user only gets back a 500 'Internal Server Error'
于 2015-03-21T23:02:21.470 回答
0

很难说,但是在我们将它们移到服务器脚本的末尾之前,我们遇到了错误问题,即使在启动服务器之后也是如此。这是使用 Express 和 Node,但可以给你一个提示。在我们在服务器文件的开头附近假设没有问题但在我们将所有错误处理移至结束后开始工作之前。不确定路由器或框架操作顺序的中间件是否有问题,但似乎解决了我们的问题。


/////////////////////////////
// Start Server
/////////////////////////////

app.listen(siteConf.port);

//////////////////////////
// Error Handling
//////////////////////////  
function NotFoundError(req, message){
    this.name = "NotFoundError";
    this.status = 404;
    this.message = message || (req.method + " " + req.url + " could not be found");
    Error.captureStackTrace(this, NotFoundError);
}
NotFoundError.prototype.__proto__ = Error.prototype;

function ProtectedResourceError(req, message){
    this.name = "ProtectedResourceError";
    this.status = 401;
    this.message = message || (req.url + " is protected");
}
ProtectedResourceError.prototype.__proto__ = Error.prototype;

function ValidationError(req, message, errors){
    this.name = "ValidationError";
    this.status = 400;
    this.message = message || ("Error when validating input for " + req.url);
    this.errors = errors;
}
ValidationError.prototype.__proto__ = Error.prototype;

function SearchError(req, message){
    this.name = "SearchError";
    this.status = 400;
    this.message = message || ("Error when searching");
}
SearchError.prototype.__proto__ = Error.prototype;

// If no route matches, throw NotFoundError
app.use(function(req, res, next) {
    console.log("No matching route for " + req.url);
    next(new NotFoundError(req));        
});

// General error handler
app.use(function(err, req, res, next) {
    //console.log("Trapped error : " + err);

    // handle exceptions
    if (err instanceof ValidationError) {
        standardResponse(req, res, {error: err.message, fields: err.errors}, err.status, err.message);
    } else if (err instanceof ProtectedResourceError) {
        standardResponse(req, res, {error: err.message}, err.status, err.message);
    } else if (err instanceof NotFoundError) {
        standardResponse(req, res, {error: err.message}, err.status, err.message);
    } else if (err instanceof SearchError) {
        standardResponse(req, res, {error: err.message}, err.status, err.message);
    } else {
        standardResponse(req, res, {error: err.message}, 500, err.message);
    }
});
于 2012-07-25T15:19:04.917 回答