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日)に加えられた変更の1つによるものです。

JavaScriptの厳密モードの新しいセマンティクスにより、CoffeeScriptは、コンストラクター関数がすべてのランタイムで名前を持つことを保証しなくなりました。議論については#2052を参照してください。

Mongooseクエリコールバック内のthrow代わりにステートメントを使用しても機能しないことに注意してください。next()

于 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

わかりにくいですが、サーバーを起動した後でも、サーバースクリプトの最後に移動するまで、エラーに関する問題が発生していました。これはNodeでExpressを使用していますが、ヒントが得られる可能性があります。これがサーバーファイルの先頭近くにある前は、問題はないと想定していましたが、すべてのエラー処理を終了した後に動作を開始しました。フレームワークの操作順序のルーターまたはミドルウェアに問題があるかどうかはわかりませんが、問題は解決したようです。


/////////////////////////////
// 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 に答える