2016-01-31 13 views
7

Sto costruendo un sito Web di esempio utilizzando Express e ho trovato qualcosa che non capisco.
Il middleware (i) di gestione degli errori dovrebbe essere l'ultimo (i) nella pipeline, se ho capito bene. Ad esempio, funziona bene:Il middleware di gestione degli errori non funziona sempre

var http = require('http'); 
var express = require('express'); 

var app = express(); 
app.set('view engine', 'jade'); 
app.set('views', './views'); 

app.use(express.static('./public')); 
http.createServer(app).listen(portNumber, function() { }); 

app.get('/hello', function(req, res) { 
    res.send('Welcome!'); 
}); 

app.use(function(err, req, res, next) { 
    res.status(500).send('something broke!'); 
}); 

app.get('/error', function(req, res, next) { 
    somethingNonExistent(2016); 
}); 

Tuttavia, se mi registro che middleware prima http.createServer chiamata, ma dopo sono stati registrati tutti gli altri middleware, non funzionerà - il mio codice non è chiamato:

var http = require('http'); 
var express = require('express'); 

var app = express(); 

app.use(express.static('./public')); 

app.use(function(err, req, res, next) { 
    res.status(500).send('something broke!'); 
}); 

http.createServer(app).listen(portNumber, function() { }); 

app.get('/hello', function(req, res) { 
    res.send('Welcome!'); 
}); 

app.get('/error', function(req, res, next) { 
    somethingNonExistent(2016); 
}); 

Cosa mi sono perso qui? La mia ipotesi è che le chiamate app.get utilizzino internamente qualche middleware e questo si incasina.
ho utilizzare Express 3.2.6 e Node.js 0.10.29, se questo fa alcuna differenza

+2

Si prega di commentare i downvotes – chester89

+0

Non sono sicuro dei downvotes, ma quello che mi ha impedito di prendere tempo per rispondere è il codice extra irrilevante. Il modo migliore per ottenere una risposta è pubblicare il caso d'uso più semplicistico che riesci a trovare, non pubblicare l'intera app. A nessuno piace molto il debug, tanto meno il debugging del codice di qualcun altro. Non è necessario il logging della console per la console, l'impostazione delle configurazioni dell'ambiente, la matematica per calcolare la durata di un giorno, ecc. 'Var app = express(); app.use (qualcosa); app.get ("/ ciao", ...);/* il tuo tentativo di gestione degli errori */' – cdbajorin

+0

@cdbajorin punto preso. Aggiornerò il post – chester89

risposta

3

Quando si definisce percorsi/middleware, il path si specifica viene utilizzato per vedere se corrisponde con le richieste in arrivo. La tua richiesta verrà sempre indirizzata alla prima partita. Una richiesta potrebbe avere più corrispondenze, quindi l'ordine è importante qui. È possibile premere il prossimo percorso/middleware corrispondente chiamando la funzione next().

Quando si monta il middleware utilizzando app.use senza specificare un percorso, ogni percorso è idoneo per il raggiungimento di tale middleware. Quindi, se è la prima cosa che monti, ogni richiesta userà quel middleware.

Se si desidera catturare tutto il gestore degli errori, è necessario il contrario: è necessario montare il middleware alla fine delle definizioni del percorso. Avrete bisogno di chiamare la funzione next nel gestore di raggiungere in realtà questo middleware:

app.get('/hello', function(req, res, next) { 
    ... 
    // Let's pretend that there was some error 
    next() 
}); 

// After all of your route definitions... 
app.use(function(req, res) { 
    res.status(500).send('something broke!'); 
}) 

Nota che se nessun percorso esiste per il percorso corrente, sarà anche colpire questo cattura tutto il middleware.

+0

si aspettava qualcosa di simile. grazie anche – chester89

+0

, sospetto che la tua risposta sia valida per entrambe le versioni 3 e 4? solo curioso – chester89

+0

Sì, questo funziona per le versioni 3 e 4. – Wex

-1

Docs

http://expressjs.com/en/guide/error-handling.html

Si definiscono di gestione degli errori middleware scorso, dopo che altre app.use() e instrada le chiamate; per esempio:

var bodyParser = require('body-parser'); 
var methodOverride = require('method-override'); 

app.use(bodyParser()); 
app.use(methodOverride()); 
app.use(function(err, req, res, next) { 
    // logic 
}); 

L'interno

Per una maggiore comprensione, si può immaginare la pipeline. Quando il controller riceve una richiesta, all'interno espresso, sembra che questo

try { 
    fn(req, res, next); // your controller 
} catch (err) { 
    next(err); 
} 

Così, allora il vostro codice di errore di tiro, si chiamerà next con err. Fondamentalmente, è lo stesso di chiamare next(new Error()). Successivamente, esprimi il tentativo di trovare il prossimo middleware con 4 argomenti nella pipeline del middleware. Nella tua situazione, il gestore degli errori ha dichiarato prima del controller ombreggiato, quindi non è coinvolto.

Tecnicamente, non c'è differenza tra controller e middleware. Opzionalmente è possibile passare il parametro next del controller e chiamarlo per passare ulteriormente attraverso la pipeline.Se non chiami next(), hai finito di elaborare la richiesta.

+0

come ha funzionato il primo frammento, in tal caso? – chester89

+0

non funziona con express @ 4 –