Esprimere la prossima funzione, a cosa serve veramente?


124

Ho cercato di trovare una buona descrizione di ciò che fa il next()metodo. Nella documentazione di Express si dice che next('route')può essere usato per saltare a quella rotta e saltare tutte le rotte intermedie, ma a volte nextviene chiamata senza argomenti. Qualcuno sa di un buon tutorial ecc. Che descrive la nextfunzione?

Risposte:


161

next()senza argomenti dice "sto scherzando, in realtà non voglio gestirlo". Torna dentro e cerca di trovare il percorso successivo che corrisponda.

Questo è utile, diciamo se vuoi avere una sorta di gestore di pagine con gli slug degli URL, così come 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 inventato dovrebbe controllare un database per una pagina con un certo slug di ID. Se ne trova uno, renderlo! se non ne trova uno, ignora questo gestore di rotte e cerca altri.

Quindi next()senza argomenti consente di fingere di non aver gestito il percorso in modo che qualcos'altro possa prenderlo invece.


O un contatore di visite con app.all('*'). Ciò ti consente di eseguire un codice di configurazione condiviso e quindi 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() {
  //...
});

Bella risposta! Ho visto anche altri usi di next, ad esempio next (err) e next ('route'). Conosci ora lo scopo di questi, quando vorresti propagare un errore e quando vorresti saltare a un determinato percorso?
Andreas Selenwall

8
@AndreasSelenwall next('route')è specifico app.VERB()e viene utilizzato quando una route ha più callback per " bypassare le restanti callback della route " .next(err) Viene utilizzato per passare a qualsiasi " middleware di errore " ( Edal post).
Jonathan Lonowski

5
Upvoted. Proprio per questa frase: "sto scherzando, in realtà non voglio gestirlo" mi hai fatto capire cosa stavo cercando. Ho visto molte domande simili e ho trovato la soluzione in una frase.
Pedro Barros

8
Chiamare next()senza argomenti in realtà non dice al sistema "non voglio gestire questo", dice semplicemente al sistema di continuare a elaborare qualsiasi middleware rimanente dopo che questo è stato fatto. Non è una condizione di errore da chiamare next(), fa parte del flusso normale. Se non chiami, next()nessun altro percorso verrà elaborato.
d512

1
Vorrei che più risposte su questo sito web fossero scritte per i profani ... "next () senza argomenti dice" sto scherzando, in realtà non voglio gestirlo "" - Perfetto per i niubbi ... (@ d512 ha un spiegazione migliore però)
daCoda

129

Nella maggior parte dei framework si riceve una richiesta e si desidera restituire una risposta. A causa della natura asincrona di Node.js, si verificano problemi con le richiamate annidate se si eseguono operazioni non banali. Per evitare che ciò accada, Connect.js (prima della v4.0, Express.js era un livello sopra connect.js) ha qualcosa che si chiama middleware che è una funzione con 2, 3 o 4 parametri.

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

La tua app Express.js è un insieme di queste funzioni.

inserisci qui la descrizione dell'immagine

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

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

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

Questo middleware viene utilizzato per elaborare eventuali errori. Mi piace fare quanto segue:

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

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

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

Se immagini la tua applicazione Express.js come uno stack, probabilmente sarai in grado di risolvere da solo molte stranezze. Ad esempio, quando aggiungi il middleware dei cookie dopo il router, ha senso che i tuoi percorsi non abbiano cookie.


3
Dove memorizzereste questa funzione di registrazione anonima?
dennismonsewicz

"Express interromperà lo stack corrente ed eseguirà tutto il middleware con 4 parametri." Mi chiedevo come Express sia in grado di eseguire middleware di gestione degli errori esatti. Grazie!
Abhishek Agarwal

75

IMHO, la risposta accettata a questa domanda non è veramente accurata. Come altri hanno affermato, si tratta davvero di controllare quando viene eseguito il prossimo handler nella catena. Ma volevo fornire un po 'più di codice per renderlo più concreto. Supponi di avere questa semplice app express:

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 fate

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

vedrai questo stampato su console:

before request handler
handling request
after request handler

Ora, se commentate la chiamata a next()in the middle handler in questo modo:

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

Vedrai questo sulla console:

before request handler
handling request

Notare che l'ultimo gestore (quello che stampa after request handler) non viene eseguito. Questo perché non stai più dicendo a Express di eseguire il prossimo gestore.

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 tornato utile? Supponiamo che tu voglia registrare tutte le richieste pervenute a un database indipendentemente dal fatto che la richiesta abbia avuto successo o meno.

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 vuoi che il secondo gestore venga eseguito, devi chiamare next()il primo gestore.

Ricorda che il nodo è asincrono, quindi non può sapere quando il callback del primo gestore è terminato. Devi dirlo chiamando next().


Sonfar la migliore risposta per me.
Norayr Ghukasyan

Bene spiegazione!
Chang

7

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


2
O il prossimo middleware.
robertklep

1

Significa semplicemente passare il controllo al gestore successivo.

Saluti


1

Notare la chiamata sopra a next (). La chiamata a questa funzione richiama la successiva funzione middleware nell'app. La funzione next () non fa parte dell'API Node.js o Express, ma è il terzo argomento passato alla funzione middleware. La funzione next () potrebbe essere chiamata qualsiasi cosa, ma per convenzione è sempre chiamata "next". Per evitare confusione, utilizzare sempre questa convenzione.


0

Domanda posta anche sull'uso del prossimo ('percorso') che sembra essere coperto una settimana dalle risposte fornite finora:

  1. UTILIZZO DI next ():

In breve: la prossima funzione middleware.

Estratto da questa documentazione ufficiale di Express JS - pagina "writing-middleware" :

"La funzione middleware myLogger stampa semplicemente un messaggio, quindi passa la richiesta alla successiva funzione middleware nello stack chiamando la funzione next ()."

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

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)

Questa pagina della documentazione di Express JS afferma "Se la funzione middleware corrente non termina il ciclo richiesta-risposta, deve chiamare next () per passare il controllo alla funzione middleware successiva. In caso contrario, la richiesta verrà lasciata in sospeso."

  1. UTILIZZO DEL successivo ('percorso'):

In breve: percorso successivo (vs. funzione middleware successiva in caso di next ())

Estratto da questa documentazione di Express JS - pagina "using-middleware" :

"Per saltare il resto delle funzioni middleware da uno stack middleware del router, chiama next ('route') per passare il controllo alla route successiva . NOTA: next ('route') funzionerà solo nelle funzioni middleware caricate utilizzando il funzioni app.METHOD () o router.METHOD ().

Questo esempio mostra un sub-stack middleware che gestisce le richieste GET al percorso / user /: id. "

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
  res.render('special')
})

0

next () è l'argomento di callback alla funzione middleware con req, e res è la richiesta http e gli argomenti di risposta a next nel codice seguente.

app.get ('/', (req, res, next) => {next ()});

Quindi next () chiama la funzione middleware passata. Se la funzione middleware corrente non termina il ciclo richiesta-risposta, dovrebbe chiamare next (), altrimenti la richiesta verrà lasciata in sospeso e andrà in timeout.

next () fn deve essere chiamato all'interno di ciascuna funzione middleware quando più funzioni middleware vengono passate ad app.use o app.METHOD, altrimenti la successiva funzione middleware non verrà chiamata (nel caso in cui venga passata più di 1 funzione middleware). Per saltare la chiamata alle restanti funzioni middleware, chiamare next ('route') all'interno della funzione middleware, dopodiché non devono essere chiamate altre funzioni middleware. Nel codice seguente, verrà chiamato fn1 e anche fn2, poiché next () è chiamato all'interno di fn1. Tuttavia, fn3 non verrà chiamato, poiché next ('route') viene chiamato all'interno di fn2.

app.get('/fetch', function fn1(req, res, next)  {
console.log("First middleware function called"); 
    next();
}, 
function fn2(req, res, next) {
    console.log("Second middleware function called"); 
    next("route");
}, 
function fn3(req, res, next) {
    console.log("Third middleware function will not be called"); 
    next();
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.