自定义错误和蓝鸟捕获ErrorClass导致无意中的行为

我正在尝试实现自定义错误的模块。

应该可以使用这个模块在应用程序的require-statement中实例化一个单独的错误:

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; 

上述的需求一class轮运作到目前为止。

现在,在我的服务中,我想明确地捕捉到这个错误:

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

如果我通过抛出MyCustomError在我的testing中拒绝了fooService.bar的承诺,这是非常好的。

但是,这只适用于我的testing和服务正在使用MyCustomError 相同的实例

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

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

蓝鸟处理的具体代码位于catch_filter.js中,你可以在这里看看。

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

如何通过比较实例来获得这个概念并运行,但是错误types本身?

干杯,
克里斯托弗

我终于想出了一个稍微不同的方法。 对于志同道合的人来说,这是结果:

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(); 

我创build了一个包含这些类的独立模块。

然后,在我的实现中,我可以单独捕获这样的错误:

 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为什么需要使用谓词函数,而不是仅仅将错误对象传递给catch子句。 但我可以用这个生活。

你也可以用catch来使用谓词函数

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