2012-10-30 12 views
77

Si è cercato di trovare una buona descrizione di ciò che fa il metodo next(). Nella documentazione Express si dice che è possibile utilizzare next('route') per saltare a quella rotta e saltare tutti i percorsi intermedi, ma a volte è possibile chiamare next senza argomenti. Qualcuno sa di un buon tutorial ecc che descrive la funzione next?Esprimi funzione successiva, a cosa serve veramente?

risposta

105

next() senza argomenti dice "sto scherzando, non voglio veramente gestirlo". Torna indietro e cerca di trovare il prossimo percorso che corrisponderebbe.

Questo è utile, diciamo se si desidera avere una sorta di gestore di pagine con url slugs, oltre a molte altre cose, ma ecco un esempio.

app.get('/:pageslug', function(req, res, next){ 
    var page = db.findPage(req.params.pageslug); 
    if (page) { 
    res.send(page.body); 
    } else { 
    next(); 
    } 
}); 

app.get('/other_routes', function() { 
    //... 
}); 

Quel codice creato deve controllare un database per una pagina con un determinato sl sl id. Se trova uno renderlo! se non ne trova uno, ignorare questo gestore di route e controllarne altri.

Quindi con next() senza argomenti è possibile fingere di non aver gestito il percorso in modo che qualcos'altro possa prelevarlo.


Oppure un contatore visite con app.all('*'). Che ti permette di eseguire alcuni codici di configurazione condivisi e poi passare ad altri percorsi per fare qualcosa di più specifico.

app.all('*', function(req, res, next){ 
    myHitCounter.count += 1; 
    next(); 
}); 

app.get('/other_routes', function() { 
    //... 
}); 
+0

Ottima risposta! Ho visto anche altri usi di next, ad es. next (err) e next ('route'). Hai ora lo scopo di questi, quando ti piacerebbe propagare un errore, e quando ti piacerebbe passare a un determinato percorso? –

+7

@AndreasSelenwall 'next ('route')' è specifico di ['app.VERB()'] (http://expressjs.com/api.html#app.VERB) e viene utilizzato quando una rotta ha più callback per "* bypassa il callback della/e restante/i. *" 'next (err)' è usato per passare a qualsiasi "[middleware di errore] (http://stackoverflow.com/a/7151775/15031)" ('E' dal post). –

+2

Venerato. Solo per questa frase: "Sto solo scherzando, non voglio davvero gestirlo" mi hai fatto capire cosa stavo cercando. Ho visto molte domande simili e ho trovato una soluzione in una frase. –

102

Nella maggior parte dei framework si ottiene una richiesta e si desidera restituire una risposta. A causa della natura asincrona di Node.js si incontrano problemi con le chiamate annidate se si stanno facendo cose non banali. Per evitare che ciò accada, Connect.js (precedente alla v4.0, Express.js era un livello in cima a connect.js) ha qualcosa che si chiama middleware che è una funzione con 2, 3 o 4 parametri.

function (<err>, req, res, next) {} 

L'app Express.js è una pila di queste funzioni.

enter image description here

Il router è speciale, è un middleware che consente di eseguire uno o più middleware per un determinato URL. Quindi è una pila all'interno di una pila.

Quindi cosa fa il prossimo? Semplice, dice alla tua app di eseguire il prossimo middleware. Ma cosa succede quando passi qualcosa al prossimo? Express interromperà lo stack corrente e eseguirà tutto il middleware che ha 4 parametri.

function (err, req, res, next) {} 

Questo middleware viene utilizzato per elaborare eventuali errori. Mi piace effettuare le seguenti operazioni:

next({ type: 'database', error: 'datacenter blew up' }); 

Con questo errore probabilmente direi all'utente che qualcosa è andato storto e registrare l'errore reale.

function (err, req, res, next) { 
    if (err.type === 'database') { 
    res.send('Something went wrong user'); 
    console.log(err.error); 
    } 
}; 

Se immagini l'applicazione Express.js come una pila, probabilmente sarai in grado di risolvere un sacco di stranezze. Ad esempio, quando aggiungi il middleware Cookie dopo il router, è logico che i tuoi percorsi non abbiano cookie.

+7

risposta eccellente. –

+3

Dove memorizzereste questa funzione di registrazione anonima? – dennismonsewicz

5

next() senza parametro richiama il gestore di route successivo nel framework.

+0

O il prossimo middleware. – robertklep

18

IMHO, la risposta accettata a questa domanda non è molto accurata. Come altri hanno affermato, si tratta in realtà di controllare quando viene eseguito il prossimo gestore della catena. Ma volevo fornire un po 'più di codice per renderlo più concreto. Diciamo che avete questa semplice applicazione espresso:

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

app.get('/user/:id', function (req, res, next) { 
    console.log('before request handler'); 
    next(); 
}); 

app.get('/user/:id', function (req, res, next) { 
    console.log('handling request'); 
    res.sendStatus(200); 
    next(); 
}); 

app.get('/user/:id', function (req, res, next) { 
    console.log('after request handler'); 
    next(); 
}); 

app.listen(3000, function() { 
    console.log('Example app listening on port 3000!') 
}); 

Se fai

curl http://localhost:3000/user/123 

si vedrà questo stampato per consolare:

before request handler 
handling request 
after request handler 

Ora, se si commento la chiamata a next() in il middle handler come questo:

app.get('/user/:id', function (req, res, next) { 
    console.log('handling request'); 
    res.sendStatus(200); 
    //next(); 
}); 

Vedrete questo sulla console:

before request handler 
handling request 

Si noti che l'ultimo gestore (quello che consente di stampare after request handler) non viene eseguito. Questo perché non stai più dicendo express per eseguire il prossimo handler.

Quindi non importa se il tuo gestore "principale" (quello che restituisce 200) ha avuto successo o meno, se vuoi che il resto del middleware funzioni, devi chiamare next().

Quando sarebbe utile? Supponiamo che tu voglia registrare tutte le richieste ricevute in qualche database, indipendentemente dal fatto che la richiesta abbia avuto o meno esito positivo.

app.get('/user/:id', function (req, res, next) { 
    try { 
     // ... 
    } 
    catch (ex) { 
     // ... 
    } 
    finally { 
     // go to the next handler regardless of what happened in this one 
     next(); 
    } 
}); 

app.get('/user/:id', function (req, res, next) { 
    logToDatabase(req); 
    next(); 
}); 

Se si desidera che il secondo gestore di correre, è necessario chiamare next() nel primo gestore.

Ricordare che il nodo è asincrono in modo che non possa sapere quando è terminata la richiamata del primo gestore. Devi dirlo chiamando lo next().

+0

Questa è una spiegazione molto chiara. Grazie. – swdon