2011-12-15 15 views
11

Por lo tanto, el general convention para las funciones de devolución de llamada en Node.js es "reservar" el primer parámetro para un error (si existe). Por ejemplo:Node.js convención para devolver varios errores a través de devolución de llamada?

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

Si tiene que devolver más de un error - dicen varios errores de validación de datos, por ejemplo - ¿Se considera mala forma de pasar una serie de objetos de error? Ejemplo:

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

O es preferible evitar arrays y devolver un único objeto con una propiedad referencia a un array (si es necesario)? Ejemplo:

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

Respuesta

9

3 años posteriores:

Cualquier persona que pone una matriz en una devolución de llamada me hará loco.

La solución correcta es devolver error como primer argumento. Si desea devolver varios errores, probablemente esté utilizando errores para casos no excepcionales.

En cuyo caso debe ir en la ranura "valor" de la devolución de llamada, es decir, el segundo argumento. El primer argumento es para un único error operacional inesperado.

Si tiene varios errores operacionales inesperados (poco probable) que puede hacer algo como esto MultiError

original:

creo que no hay nada malo con la devolución de una serie de errores.

Aunque podría devolver una nueva costumbre ValidationError que tiene una propiedad "messages" que es una matriz.

una)

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 para notar que el error debería ser efectivamente un 'Error' – laconbass

+1

Te estoy bajando por el *" Creo que no hay nada de malo en devolver una serie de errores "*, pero otorgándote una recompensa de 100 puntos * (como nadie más respondió cuando lo estimulé para llamar más la atención, así que no tengo a nadie más para darle los puntos) *. Tal vez la ganancia neta de 98 puntos será un pequeño incentivo para revisar y volver a reflexionar sobre el tema: -P ... porque yo creo que el canon es que una serie de errores no es un parámetro válido err en el Nodo. – HostileFork

+0

desafío @HostileFork aceptado :) Se corrigió la respuesta. – Raynos

4

Encontrado esta pregunta a través de una búsqueda de la misma cuestión. Aunque miré a mi alrededor y llegué a la conclusión de que no creo que err sea cualquier cosa menos un Error o null.

La mejor fuente de "autoridad" que he encontrado es el tema de ayuda de Nodejitsu:

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

En Node.js, se considera una práctica estándar para controlar los errores en las funciones asíncronas devolviéndolos como el primer argumento para la devolución de llamada de la función actual. Si hay un error, al primer parámetro se le pasa un objeto Error con todos los detalles. De lo contrario, el primer parámetro es nulo.

Pero creo que se puede argumentar intuitivamente por qué debería ser así.Aunque hay una gran cantidad de pruebas en if (err) código para decidir si algo es o no un error, no debe pasar 0 o false o undefined o NaN o una cadena vacía. Debería poder probar con if (err == null) si lo desea.

Pasando volver algo en el campo err es no nulo, pero no coincide con if (err instanceof Error) parece poco fiable. Así que sugeriría no usar matrices u objetos. Si lo hizo, tenga en cuenta también que ninguno de los errores en su matriz identificará la ubicación donde se creó el error agregado. Ese es el punto donde ocurrió el "error real", porque fue el momento de la decisión que los errores que se le dieron no eran algo que pudiera manejar.

Sin embargo, esto significa que había necesidad de un poco más de trabajo para conseguir que:

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

Un poco exagerado, tal vez. Pero si realmente no puede escoger un error para representar la agregación, y pensar que alguien podría estar interesado en el conjunto de errores en vez de uno, parecería (?) Eso es lo que se quiere hacer ... permite la llamante para examinar la matriz errs si así lo desean.

+0

en lugar de 'MultipleError.prototype proto__' .__, que puede [prevenir JS optimización] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/The_performance_hazards_of__%5B%5BPrototype%5D% 5D_mutation), es posible que desee hacer 'MultipleError.prototype = Object.create (Error.prototype, {constructor: {valor: MultipleError}, nombre: {valor: 'MultipleError'}, toString: {valor: function() {//...}}}); ', con la ventaja añadida de hacer que esas propiedades en' MultipleError' no sean configurables y no enumerables. – snickle

Cuestiones relacionadas