【问题标题】:Node.js convention for returning multiple errors via callback?Node.js 通过回调返回多个错误的约定?
【发布时间】:2012-01-20 18:31:33
【问题描述】:

因此,Node.js 中回调函数的general convention 是为错误“保留”第一个参数(如果存在)。例如:

callSomeBlockingFcn( function callbackWhenDone(err, result) {
  if( err ) ...
});

如果您需要返回多个错误(例如多个数据验证错误),传递一组错误对象是否被认为是糟糕的形式?示例:

var callSomeBlockingFcn = function(callback) {
  // multiple errors to report back...
  callback( [ err1, err2, ...] );
}

或者最好避免使用数组并返回具有引用数组的属性的单个对象(如果需要)?示例:

var callSomeBlockingFcn = function(callback) {
  // multiple errors to report back...
  callback( { errors: [ err1, err2, ...] } );
}

【问题讨论】:

    标签: javascript node.js error-handling


    【解决方案1】:

    3 年后

    任何将数组放入回调的人都会让我发疯。

    正确的解决方案是返回 error 作为第一个参数。如果您想返回多个错误,您可能会在非异常情况下使用错误。

    在这种情况下,它应该进入回调的“值”槽,即第二个参数。第一个参数是针对单个意外操作错误。

    如果您有多个意外的操作错误(不太可能),您可以这样做MultiError

    原创

    我认为返回错误数组并没有错。

    虽然您可以返回一个新的自定义 ValidationError,它的属性 "messages" 是一个数组。

    一)

    function validateX(x, cb) {
      ...
      if (errorMessages) {
        return cb(errorMessages);
      }
    }
    

    b)

    function ValidationError(msgs) {
      this.messages = msgs;
    }
    
    function validateX(x, cb) {
      ...
      if (errorMessages) {
        return cb(new ValidationError(errorMessages));
      }
    }
    

    【讨论】:

    • 我对你投了反对票 “我认为返回一系列错误没有什么问题”,但奖励你 100 分赏金(因为没有人其他人在我奖励它以引起更多关注时回答了,所以我没有其他人可以给予积分)。也许 98 点的净收益将是重新审视和重新思考这个问题的一个小动机:-P ...因为我确实认为标准是一系列错误不是 Node 中的有效 err 参数。
    • @HostileFork 挑战已接受 :) 修正了答案。
    • @Raynos 投票相应地更正了。验证是值得的。 :-)
    • AggregateError 对象呢?
    【解决方案2】:

    通过搜索相同的问题找到了这个问题。虽然我环顾四周,得出的结论是,我不认为 err 应该是错误或 null

    我发现的最好的“权威”来源是 Nodejitsu 的帮助主题:

    http://docs.nodejitsu.com/articles/errors/what-are-the-error-conventions

    在 node.js 中,处理异步函数中的错误被认为是标准做法,方法是将它们作为第一个参数返回给当前函数的回调。如果有错误,第一个参数将传递一个带有所有详细信息的 Error 对象。否则,第一个参数为空。

    但我认为你可以根据直觉来论证为什么会这样。尽管代码中有很多 if (err) 测试来确定是否存在错误,但您不应传递 0falseundefinedNaN 或空字符串。如果您愿意,您应该可以使用if (err == null) 进行测试。

    在 err 字段中传回非空但不匹配 if (err instanceof Error) 的内容似乎很狡猾。所以我建议不要使用数组或对象。如果您这样做了,还请注意,您的数组中的任何错误都不会识别创建聚合错误的位置。这就是“真正的错误”发生的地方,因为它是做出决定的那一刻,它给出的错误是它无法处理的。

    但是,这意味着您需要做更多的工作才能做到这一点:

    function MultipleError (errs) {
        // http://stackoverflow.com/a/13294728/211160
    
        if (!(this instanceof MultipleError)) {
            return new MultipleError(errs);
        }
    
        Error.call(this);
        this.errs = errs;
    
        // captureStackTrace is V8-only (so Node, Chrome)
        // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
    
        Error.captureStackTrace(this, MultipleError);
    };
    
    MultipleError.prototype.__proto__ = Error.prototype;
    MultipleError.prototype.name = 'MultipleError';
    MultipleError.prototype.toString = function () {
       return 'MultipleError: [\n\t' + this.errs.join(',\n\t') + '\n]';
    }
    

    也许有点矫枉过正。但是,如果您真的不能选择一个错误来表示聚合,并且认为有人可能对一组错误而不是一个错误感兴趣,那么看起来(?)这就是您想要做的......允许调用者可以根据需要检查 errs 数组。

    【讨论】:

    • 而不是MultipleError.prototype.__proto__,它可以prevent JS optimization,你可能想要做MultipleError.prototype = Object.create(Error.prototype, { constructor: { value: MultipleError }, name: { value: 'MultipleError' }, toString: { value: function () { //... } } });,额外的好处是使MultipleError上的这些属性不可配置和不可枚举。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多