2011-12-15 15 views
11

Quindi il general convention per le funzioni di callback in Node.js è di "riservare" il primo parametro per un errore (se ne esiste uno). Per esempio:Convenzione Node.js per la restituzione di più errori tramite callback?

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

Se è necessario restituire più di un errore - dicono errori di convalida dati multipli, per esempio - è considerato cattiva forma di passare un array di oggetti di errore? Esempio:

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

O è preferibile evitare array e restituire un singolo oggetto con una proprietà fa riferimento a un array (se necessario)? Esempio:

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

risposta

9

3 anni più tardi:

Chiunque che mette una matrice in un callback farà impazzire.

La soluzione corretta è restituire un error come primo argomento. Se vuoi restituire più errori, probabilmente stai usando errori per casi non eccezionali.

In tal caso dovrebbe andare nello slot "valore" del callback, ovvero il secondo argomento. Il primo argomento riguarda un singolo errore operativo inatteso.

Se si dispone di più errori operativi imprevisti (improbabile) si può fare qualcosa di simile MultiError

originale:

penso che ci sia niente di sbagliato con il ritorno di una serie di errori.

Anche se è possibile restituire una nuova ordinazione ValidationError che ha una proprietà "messages" che è una matrice.

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 per notare che l'errore dovrebbe essere effettivamente un 'Errore' – laconbass

+1

Sto downvoting per il *" Penso che non ci sia nulla di sbagliato nel restituire un array di errori "*, ma assegnando un valore di 100 punti * (come nessun altro ha risposto quando l'ho esagerato per attirare più attenzione, quindi non ho nessun altro a cui dare i punti) *. Forse il guadagno netto di 98 punti sarà un piccolo incentivo per rivisitare e ripensare il problema :-P ... perché penso che il canone sia che una serie di errori non è un parametro err valido nel Nodo. – HostileFork

+0

@HostileFork challenge accepted :) Risolto il problema. – Raynos

4

Trovato questa domanda tramite una ricerca per lo stesso problema. Anche se mi sono guardato attorno e sono giunto alla conclusione che non credo che lo err debba essere tutto tranne un errore o null.

La fonte migliore "autorevole" che ho trovato è argomento della guida di Nodejitsu:

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

In node.js, è considerato una pratica standard per gestire gli errori di funzioni asincrone restituendole come il primo argomento del callback della funzione corrente. Se c'è un errore, al primo parametro viene passato un oggetto Error con tutti i dettagli. Altrimenti, il primo parametro è nullo.

Ma penso che si possa fare una discussione dall'intuizione sul motivo per cui dovrebbe essere così.Sebbene ci siano un sacco di test if (err) nel codice per decidere se qualcosa è stato o non è stato un errore, non si dovrebbe passare 0 o false o undefined o NaN o una stringa vuota. Dovresti essere in grado di testare con if (err == null) se lo desideri.

Passare indietro qualcosa nel campo err che non è nullo ma non corrisponde a if (err instanceof Error) sembra inopportuno. Quindi suggerirei di non usare matrici o oggetti. Se lo hai fatto, nota anche che nessuno degli errori nell'array identificherà la posizione in cui è stato creato l'errore di aggregazione. Questo è il punto in cui si è verificato il "vero errore", perché è stato il momento della decisione che gli errori che è stato dato non erano qualcosa che potesse gestire.

Tuttavia, questo significa che avresti bisogno di un po 'più di lavoro per ottenere che:

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 po' eccessivo, forse. Ma se davvero non puoi scegliere un errore per rappresentare l'aggregazione e pensare che qualcuno potrebbe essere interessato all'insieme di errori invece di uno solo, sembrerebbe (?) Che è ciò che vorresti fare ... Permette al chiamante per esaminare l'array errs se lo desidera.

+0

Invece di 'MultipleError.prototype .__ proto__', che può [impedire l'ottimizzazione JS] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/The_performance_hazards_of__%5B%5BPrototype%5D% 5D_mutation), potresti voler eseguire 'MultipleError.prototype = Object.create (Error.prototype, {costruttore: {valore: MultipleError}, nome: {valore: 'MultipleError'}, toString: {valore: function() {//...}}}); ', con l'ulteriore vantaggio di rendere tali proprietà su' MultipleError' non configurabili e non enumerabili. – snickle

Problemi correlati