2012-11-10 7 views
11

Ho app in Node.js e Express. Devo scrivere test per questo. Ho un problema con la gestione degli errori delle app Express. Ho trovato questo How do I catch node.js/express server errors like EADDRINUSE?, ma non funziona per me, non so perché. Voglio gestire gli errori, che possono verificarsi mentre expressApp.listen() è in esecuzione (EADDRINUSE, EACCES ecc.).L'app Node.js Express gestisce gli errori di avvio

express = require('express') 
listener = express() 

#doesn't work for me 
listener.on('uncaughtException', (err) -> 
    #do something 
) 

#doesn't work too 
listener.on("error", (err) -> 
    #do something 
) 

#this works, but it caughts all errors in process, I want only in listener 
process.on('uncaughtException', (err) -> 
    #do something 
) 

listener.listen(80) #for example 80 to get error 

Qualche idea?

+0

'errore' 'listener.on, ...' dovrebbe funzionare. Fa semplicemente il normale stack trace e crash anche se quella linea è lì? – loganfsmyth

+0

Sì, se faccio questo 'listener.listen (80)' stampa traccia dello stack e si blocca.Anche con 'listener.on' errore ', ...' Forse l'errore si è verificato in questo caso non è l'errore Express e questo è il motivo per cui non gestisce. Ma è solo supposizione. –

risposta

20

Prima di tutto, expressJS non lancia l'evento uncaughtException, il processo funziona, quindi non sorprende che il tuo codice non funzioni.

Quindi utilizzare: process.on('uncaughtException',handler) invece.

Avanti, expressJS fornisce già un mezzo standard di gestione degli errori, che è quello di utilizzare la funzione di middleware che fornisce per questo scopo, come in:

app.configure(function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

Questa funzione restituisce un messaggio di errore al client, con optional stacktrace ed è documentato allo connectJS errorHandler.

(Si noti che errorHandler è in realtà parte di connectJS ed è esposto solo da expressJS.)

Se il comportamento del errorHandler esistente fornisce non è sufficiente per le vostre esigenze, la sua sorgente si trova a connectJS's errorHandler middleware e può essere facilmente modificata per soddisfare le tue esigenze.

Naturalmente, piuttosto che modificare direttamente questa funzione, il modo "corretto" per farlo è quello di creare il proprio errorHandler, utilizzando la versione connectJS come punto di partenza, come in:

var myErrorHandler = function(err, req, res, next){ 
    ... 
    // note, using the typical middleware pattern, we'd call next() here, but 
    // since this handler is a "provider", i.e. it terminates the request, we 
    // do not. 
}; 

e installare in expressJS come:

app.configure(function(){ 
    app.use(myErrorHandler); 
}); 

Vedi Just Connect it, Already per una spiegazione dell'idea di connectJS di filter e provider middleware e How To Write Middleware for Connect/Express per un tutorial ben scritto.

Si potrebbe anche trovare questi utili:

Infine, un'ottima fonte di informazioni per quanto riguarda expressJS test può essere trovato in its own tests.

+0

+1, risposta approfondita molto buona! – Menztrual

+0

Grazie per spiegazioni così dettagliate, sarebbe comunque utile. Non è necessario gestire gli errori durante la gestione della richiesta web. Ho bisogno di creare un server e chiamare app.listen (...). Ora capisco che qui è necessaria la gestione degli errori di Node.js, non il middleware in Express. process.on ('uncaughtException', handler) è accettabile nel mio caso. –

+0

@Piane_Ramso, quindi sì, aggiungere i propri gestori di eventi a 'process.on ('uncaughtException')' è decisamente la strada da percorrere. Se sei curioso, il codice sottostante che elabora le eccezioni "non rilevate" si trova nella (o vicino) riga # 1739 in [node.cc] (https://github.com/joyent/node/blob/master/src/ node.cc) –

57

Questo dovrebbe fare il trucco:

listener.listen(80).on('error', function(err) { }); 

Cosa listener.listen realmente fa è creare un server HTTP e chiamare ascoltare su di esso:

app.listen = function(){ 
    var server = http.createServer(this); 
    return server.listen.apply(server, arguments); 
}; 
+10

È incredibile che questa sia la risposta più semplice e corretta, e che non abbia uptotes! Il trucco è capire che l'oggetto webServer viene restituito da app.listen. Io uso questo: '' 'app.listen (80, function() { console.log ('success'); }). ('Error', function (err) { if (err.errno === 'EADDRINUSE') { console.log ('port busy'); } else { console.log (err); } }); '' ' –

+0

Non capisco che il tuo codice stia funzionando. se stai chiamando il nodo app.listen già un http.createServer sotto il cofano pensavo o stai praticamente ignorando il metodo nativo app.listen() e lo stai sovrascrivendo con il tuo codice lì? – PositiveGuy

+0

La prima riga di codice è ciò che dovrebbe essere usato, tutto il resto è la spiegazione del perché funziona. –