2015-11-19 39 views
8

我想实现自定义错误模块。自定义错误和蓝鸟的ErrorClass捕获导致无意中的行为

它应该是可能的实例使用此模块的应用程序的要求,声明中的个别错误:

var MyCustomError = require('custom-error')('MyCustomError'); 

这是模块:

'use strict'; 

var _CACHE = {}; 

function initError(name) { 
    function CustomError(message) { 
    this.name = name; 
    this.message = message; 
    } 
    CustomError.prototype = Object.create(Error.prototype); 
    CustomError.prototype.constructor = CustomError; 
    _CACHE[name] = CustomError; 
} 

function createCustomError(name) { 
    if (!_CACHE[name]) { 
    initError(name); 
    } 
    return _CACHE[name]; 
} 

module.exports = createCustomError; 

的要求,一个班轮以上工作到目前为止。

现在,在我的服务,我想明确地抓住这个错误:

var MyCustomError = require('custom-error')('MyCustomError') 
// ... 
return fooService.bar() 
    .catch(MyCustomError, function (error) { 
     logger.warn(error); 
     throw error; 
    }) 

如果我通过投掷MyCustomError这是伟大的工作拒绝fooService.bar的在我的测试的承诺。

但是,这只适用于我的测试和服务使用MyCustomError的相同实例

例如,如果我删除了我的自定义错误模块中的缓存机制,catch将不会被达到/执行,因为蓝鸟不知道这两个错误是相同类型的:

function createCustomError(name) { 
    //if (!_CACHE[name]) { 
    initError(name); 
    //} 
    return _CACHE[name]; 
} 

蓝鸟的处理的具体代码位于catch_filter.js,你可以看看right here

尽管该方法在我的应用程序中起作用,但一旦多个模块使用自定义错误模块并且不再给出相同实例的共享,这将会更快导致问题。

我怎样才能得到这个概念和运行由比较实例,但错误类型本身?

干杯,
克里斯托弗

回答

3

我终于想出了一个略有不同的方法。对于志同道合的人,这就是结果:

ErrorFactory

var 
    vsprintf = require("sprintf-js").vsprintf; 

function CustomErrorFactory(code, name, httpCode, message) { 

    // Bluebird catcher 
    this.predicate = function (it) { 
    return it.code === code; 
    }; 

    this.new = function (messageParameters, details) { 
    return new CustomError(messageParameters, details); 
    }; 

    this.throw = function (messageParameters, details) { 
    throw new CustomError(messageParameters, details); 
    }; 

    function CustomError(messageParameters, details) { 
    this.code = code; 
    this.name = name; 
    this.message = vsprintf(message, messageParameters); 
    this.httpCode = httpCode; 
    this.details = details || {}; 

    // Important: Do not swallow the stacktrace that lead to here. 
    // @See http://stackoverflow.com/questions/8802845/inheriting-from-the-error-object-where-is-the-message-property 
    Error.captureStackTrace(this, CustomError); 
    } 

    // CustomError must be instance of the Error-Object 
    CustomError.prototype = Object.create(Error.prototype); 
    CustomError.prototype.constructor = CustomError; 
} 

module.exports = CustomErrorFactory; 

错误

var 
    ErrorFactory = require("./ErrorFactory"); 

function initErrors() { 
    return { 
    Parameter: { 
     Missing: new ErrorFactory('1x100', 'ParameterMissing', 400, 'Parameter "%s" missing'), 
     Invalid: new ErrorFactory('1x200', 'ParameterInvalid', 400, 'Parameter "%s" invalid') 
     //.. 
    }, 
    Access: { 
     NotAccessible: new ErrorFactory('3x100', 'AccessNotAccessible', 403, 'Resource "%s" is not accessible for "%s"'), 
     //.. 
    }, 
    // ... 
    Request: { 
     //.. 
    } 
    }; 
} 

module.exports = initErrors(); 

我创建一个包含这些类单独的模块。

然后,在我的实现,我能赶上象这样的错误单独:

function foo(request, reply) { 

    return bluebird 
    .resolve(bar) 
    .then(reply) 

    .catch(Errors.Parameter.Missing.predicate, function() { 
     return reply(boom.badRequest()); 
    }) 

    .catch(Errors.Entity.NotFound.predicate, function() { 
     return reply({}).code(204); 
    }) 

    .catch(Errors.Entity.IllegalState.predicate, function (error) { 
     return reply(boom.badImplementation(error.message)); 
    }) 

    // any other error 
    .catch(function (error) { 
     return reply(boom.badImplementation(error.message)); 
    }); 
} 

投掷

Errors.Entity.IllegalState.throw(['foo', 'bar']); 
// or 
throw Errors.Entity.IllegalState.new(['foo', 'bar']); 

要求

Errors = require('errors'); // all 
EntityErors = require('errors').Entity; // one group 
EntityNotFoundError = require('errors').Entity.NotFound; // one particular 

的唯一的事情是什么我还是不理解id为什么需要使用谓词函数而不是将错误对象传递给catc H-条款。但我可以以此为生。

3

你也可以使用断言功能与捕获

function isMyCustomError(f) { 
    return f instanceof Error && f.name === "MyCustomError"; 
} 
+0

Esailija嗨,因为我没有在一两天内的声誉也得到了自动分配给您的登录。幸运的是,因为你是蓝鸟的开发者,你应该得到它:) 代码:我没有看到你的观点如何批准处理?你谈论传统的试管捕捉处理而不考虑蓝鸟吗? –

+0

@Christopher这将只适用于蓝鸟 – Esailija

+0

所以这正是我在上面的例子中所做的 - 比如'catch(Errors.Entity.IllegalState.predicate,..)' –

相关问题