2011-12-15 23 views
11

Vì vậy, general convention cho các chức năng gọi lại trong Node.js là "đặt trước" tham số đầu tiên cho một lỗi (nếu có). Ví dụ:Quy ước Node.js để trả lại nhiều lỗi thông qua gọi lại?

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

Nếu bạn cần trả về nhiều lỗi - ví dụ: nhiều lỗi xác thực dữ liệu - được coi là biểu mẫu nghèo để truyền một mảng các đối tượng lỗi? Ví dụ:

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

Hoặc tốt hơn là tránh mảng và trả về một đối tượng duy nhất có thuộc tính tham chiếu mảng (nếu cần)? Ví dụ:

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

Trả lời

9

3 năm sau:

Bất cứ ai mà đặt một mảng trong một callback sẽ làm cho tôi điên.

Giải pháp đúng là trả về một đối số đầu tiên là error. Nếu bạn muốn trả lại nhiều lỗi, có thể bạn đang sử dụng lỗi cho các trường hợp không đặc biệt.

Trong trường hợp này, nó sẽ đi vào vị trí "giá trị" của cuộc gọi lại, tức là đối số thứ hai. Đối số đầu tiên là một lỗi hoạt động không mong muốn duy nhất.

Nếu bạn có nhiều lỗi hoạt động bất ngờ (không), bạn có thể làm điều gì đó như MultiError

gốc này:

Tôi nghĩ rằng không có gì sai với trả lại một mảng các lỗi là.

Mặc dù bạn có thể trả lại tùy chỉnh mới ValidationError có thuộc tính "messages" là một mảng.

một)

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)); 
    } 
} 
+0

+1 để lưu ý rằng lỗi có hiệu quả sẽ là 'Lỗi' – laconbass

+1

Tôi đang giảm giá bạn cho *" Tôi nghĩ không có gì sai khi trả về một loạt lỗi "*, nhưng tặng bạn 100 điểm thưởng * (như không ai khác trả lời khi tôi thưởng cho nó để thu hút thêm sự chú ý vì vậy tôi không có ai khác để đưa ra các điểm) *. Có lẽ 98 điểm đạt được sẽ là một động cơ nhỏ để xem lại và suy nghĩ lại vấn đề: -P ... bởi vì tôi nghĩ rằng canon là một mảng các lỗi không phải là một tham số err hợp lệ trong Node. – HostileFork

+0

@HostileFork thách thức được chấp nhận :) Cố định câu trả lời. – Raynos

4

Tìm thấy câu hỏi này qua một tìm kiếm cho cùng một vấn đề. Mặc dù tôi nhìn xung quanh và đi đến kết luận rằng tôi không tin rằng err nên là bất cứ điều gì nhưng một lỗi hoặc null.

tốt nhất "có thẩm quyền" nguồn tôi đã tìm thấy là Nodejitsu của chủ đề trợ giúp:

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

Trong Node.js, nó được coi là tiêu chuẩn thực hiện để xử lý lỗi trong chức năng không đồng bộ bằng cách trả lại chúng như đối số đầu tiên cho hàm gọi lại của hàm hiện tại. Nếu có lỗi, thông số đầu tiên được chuyển qua đối tượng Lỗi với tất cả chi tiết. Nếu không, tham số đầu tiên là null.

Nhưng tôi nghĩ rằng bạn có thể sắp xếp làm cho một đối số từ trực giác là tại sao nó phải như vậy.Mặc dù có rất nhiều bài kiểm tra if (err) trong mã để quyết định xem có lỗi gì hay không, nhưng bạn không nên vượt qua 0 hoặc false hoặc undefined hoặc NaN hoặc chuỗi trống. Bạn sẽ có thể thử nghiệm với if (err == null) nếu bạn muốn.

Chuyển lại nội dung nào đó trong trường lỗi không phải là rỗng nhưng không khớp với if (err instanceof Error) có vẻ tinh tế. Vì vậy, tôi khuyên bạn không nên sử dụng mảng hoặc đối tượng. Nếu bạn đã làm, cũng lưu ý rằng không có lỗi nào trong mảng của bạn sẽ xác định vị trí mà lỗi tổng hợp đã được tạo. Đó là điểm mà "lỗi thực sự" xảy ra, bởi vì đó là thời điểm quyết định rằng các lỗi được đưa ra không phải là thứ mà nó có thể xử lý được.

Tuy nhiên, điều này có nghĩa là bạn sẽ cần phải làm việc nhiều hơn một chút để nhận được rằng:

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]'; 
} 

Một overkill chút, có lẽ. Nhưng nếu bạn thực sự không thể chọn lỗi để biểu diễn tập hợp và nghĩ rằng ai đó có thể quan tâm đến tập hợp các lỗi thay vì chỉ một, có vẻ như (?) Đó là điều bạn muốn làm ... cho phép người gọi để kiểm tra các mảng errs nếu họ muốn.

+0

Thay vì 'MultipleError.prototype .__ proto__', có thể [ngăn chặn tối ưu hóa JS] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/The_performance_hazards_of__%5B%5BPrototype%5D% 5D_mutation), bạn có thể muốn thực hiện 'MultipleError.prototype = Object.create (Error.prototype, {constructor: {value: MultipleError}, name: {value: 'MultipleError'}, toString: {value: function() {//...}}}); ', với tiền thưởng thêm làm cho các thuộc tính đó trên' MultipleError' không thể cấu hình và không thể đếm được. – snickle

Các vấn đề liên quan