Express nächste Funktion, wofür ist es wirklich?

124

Ich habe versucht, eine gute Beschreibung der Funktionsweise der next()Methode zu finden . In der Express-Dokumentation heißt es, dass next('route')damit zu dieser Route gesprungen und alle dazwischen liegenden Routen übersprungen werden können, manchmal nextjedoch ohne Argumente aufgerufen wird. Kennt jemand ein gutes Tutorial usw., das die nextFunktion beschreibt ?

Andreas Selenwall
quelle

Antworten:

159

next()ohne Argumente heißt es "nur ein Scherz, ich möchte eigentlich nicht damit umgehen". Es geht wieder hinein und versucht, die nächste passende Route zu finden.

Dies ist nützlich, wenn Sie beispielsweise einen Seitenmanager mit URL-Slugs und vielen anderen Dingen haben möchten, aber hier ist ein Beispiel.

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() {
  //...
});

Dieser zusammengesetzte Code sollte eine Datenbank auf eine Seite mit einem bestimmten ID-Slug überprüfen. Wenn es einen findet, rendern Sie es! Wenn es keinen findet, ignorieren Sie diesen Routen-Handler und suchen Sie nach anderen.

Also next()ohne Argumente ermöglicht es Ihnen , so zu tun , nicht den Weg zu behandeln , so dass etwas anderes es stattdessen abholen kann.


Oder ein Trefferzähler mit app.all('*'). Auf diese Weise können Sie gemeinsam genutzten Setup-Code ausführen und dann zu anderen Routen wechseln, um etwas Spezifischeres zu tun.

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

app.get('/other_routes', function() {
  //...
});
Alex Wayne
quelle
Gute Antwort! Ich habe auch eine andere Verwendung von next gesehen, z. B. next (err) und next ('route'). Haben Sie jetzt den Zweck dieser, wann möchten Sie einen Fehler verbreiten und wann möchten Sie zu einer bestimmten Route springen?
Andreas Selenwall
8
@AndreasSelenwall next('route')spezifisch ist app.VERB()und verwendet wird , wenn eine Route mehrere Rückrufe „hat Bypass der verbleibenden Route Rückruf (s).next(err)Verwendet wird , um alle „zu springen Fehlermiddleware “ ( Eaus dem post).
Jonathan Lonowski
5
Upvoted. Nur für diesen Satz: "Nur ein Scherz, ich will damit eigentlich nicht umgehen" hast du mir verständlich gemacht, wonach ich gesucht habe. Ich sah viele ähnliche Fragen und fand eine Lösung in einem Satz.
Pedro Barros
8
Das Aufrufen next()ohne Argumente sagt dem System nicht wirklich "Ich möchte das nicht erledigen", sondern weist das System lediglich an, die verbleibenden Middlewares weiter zu verarbeiten, nachdem diese erledigt sind. Es ist keine Fehlerbedingung zum Aufrufen next(), es ist Teil des normalen Ablaufs. Wenn Sie nicht anrufen, werden überhaupt next()keine anderen Routen verarbeitet.
d512
1
Ich wünschte, mehr Antworten auf dieser Website wären für den Laien geschrieben worden ... 'next () ohne Argumente sagt "nur ein Scherz, ich möchte nicht wirklich damit umgehen"' - Perfekt für Noobs ... (@ d512 hat eine bessere Erklärung)
daCoda
129

In den meisten Frameworks erhalten Sie eine Anfrage und möchten eine Antwort zurückgeben. Aufgrund der asynchronen Natur von Node.js treten Probleme mit verschachtelten Rückrufen auf, wenn Sie nicht triviale Aufgaben ausführen. Um dies zu verhindern, verfügt Connect.js (vor Version 4.0 war Express.js eine Schicht über connect.js) über eine sogenannte Middleware, eine Funktion mit 2, 3 oder 4 Parametern.

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

Ihre Express.js-App ist ein Stapel dieser Funktionen.

Geben Sie hier die Bildbeschreibung ein

Der Router ist etwas Besonderes. Mit dieser Middleware können Sie eine oder mehrere Middleware für eine bestimmte URL ausführen. Es ist also ein Stapel innerhalb eines Stapels.

Was macht der nächste? Ganz einfach, es weist Ihre App an, die nächste Middleware auszuführen. Aber was passiert, wenn Sie etwas an das nächste weitergeben? Express bricht den aktuellen Stack ab und führt die gesamte Middleware mit 4 Parametern aus.

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

Diese Middleware wird verwendet, um Fehler zu verarbeiten. Ich mache gerne folgendes:

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

Mit diesem Fehler würde ich dem Benutzer wahrscheinlich mitteilen, dass ein Fehler aufgetreten ist, und den tatsächlichen Fehler protokollieren.

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

Wenn Sie sich Ihre Express.js-Anwendung als Stapel vorstellen, können Sie wahrscheinlich selbst eine Menge Verrücktheiten beheben. Wenn Sie beispielsweise Ihre Cookie-Middleware nach dem Router hinzufügen, ist es sinnvoll, dass Ihre Routen keine Cookies enthalten.

Pickels
quelle
3
Wo würden Sie diese anonyme Protokollierungsfunktion speichern?
Dennismonsewicz
"Express bricht den aktuellen Stack ab und führt die gesamte Middleware mit 4 Parametern aus." Ich habe mich gefragt, wie Express exakte Fehlerbehandlungs-Middlewares ausführen kann. Vielen Dank!
Abhishek Agarwal
74

IMHO ist die akzeptierte Antwort auf diese Frage nicht wirklich richtig. Wie andere gesagt haben, geht es wirklich darum zu steuern, wann der nächste Handler in der Kette ausgeführt wird. Aber ich wollte etwas mehr Code bereitstellen, um ihn konkreter zu machen. Angenommen, Sie haben diese einfache Express-App:

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!')
});

Wenn Sie tun

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

Sie sehen dies auf der Konsole gedruckt:

before request handler
handling request
after request handler

Wenn Sie nun den Aufruf an next()den mittleren Handler wie folgt auskommentieren:

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

Sie sehen dies auf der Konsole:

before request handler
handling request

Beachten Sie, dass der letzte Handler (derjenige, der druckt after request handler ) nicht ausgeführt wird. Das liegt daran, dass Sie Express nicht mehr anweisen, den nächsten Handler auszuführen.

Es spielt also keine Rolle, ob Ihr "Haupt" -Handler (der 200 zurückgibt) erfolgreich war oder nicht. Wenn Sie möchten, dass der Rest der Middleware ausgeführt wird, müssen Sie anrufen next().

Wann würde sich das als nützlich erweisen? Angenommen, Sie möchten alle Anforderungen protokollieren, die in einer Datenbank eingegangen sind, unabhängig davon, ob die Anforderung erfolgreich war oder nicht.

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();
});

Wenn der zweite Handler ausgeführt werden soll, müssen Sie next()den ersten Handler aufrufen .

Denken Sie daran, dass der Knoten asynchron ist, sodass er nicht wissen kann, wann der Rückruf des ersten Handlers beendet ist. Sie müssen es durch einen Anruf sagen next().

d512
quelle
Sonfar die beste Antwort für mich.
Norayr Ghukasyan
Gute Erklärung!
Chang
7

next () ohne Parameter ruft den nächsten Routenhandler ODER die nächste Middleware im Framework auf.

Kyasar
quelle
2
Oder die nächste Middleware.
Robertklep
1

Es bedeutet einfach, die Kontrolle an den nächsten Handler weiterzugeben.

Prost

Gammer
quelle
1

Beachten Sie den obigen Aufruf von next (). Durch Aufrufen dieser Funktion wird die nächste Middleware-Funktion in der App aufgerufen. Die next () -Funktion ist kein Teil der Node.js- oder Express-API, sondern das dritte Argument, das an die Middleware-Funktion übergeben wird. Die next () -Funktion kann beliebig benannt werden, wird jedoch konventionell immer als "next" bezeichnet. Verwenden Sie immer diese Konvention, um Verwirrung zu vermeiden.

Hukmaram
quelle
0

Die Frage wurde auch nach der Verwendung der nächsten ("Route") gestellt, die in den bisher bereitgestellten Antworten eine Woche lang behandelt zu werden scheint:

  1. NUTZUNG VON next ():

Kurzum: nächste Middleware-Funktion.

Auszug aus dieser offiziellen Express JS-Dokumentation - Seite "Writing Middleware" :

"Die Middleware-Funktion myLogger druckt einfach eine Nachricht und leitet die Anforderung durch Aufrufen der next () -Funktion an die nächste Middleware-Funktion im Stapel weiter."

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)

Auf dieser Seite der Express JS-Dokumentation heißt es: "Wenn die aktuelle Middleware-Funktion den Anforderungs-Antwort-Zyklus nicht beendet, muss next () aufgerufen werden, um die Steuerung an die nächste Middleware-Funktion zu übergeben. Andernfalls bleibt die Anforderung hängen."

  1. NUTZUNG VON next ('route'):

Kurzum: nächste Route (im Vergleich zur nächsten Middleware-Funktion bei next ())

Auszug aus dieser Express JS-Dokumentation - Seite "Using Middleware" :

"Um die restlichen Middleware-Funktionen von einem Router-Middleware-Stack zu überspringen, rufen Sie next ('route') auf, um die Steuerung an die nächste Route zu übergeben . HINWEIS: next ('route') funktioniert nur in Middleware-Funktionen, die mithilfe von geladen wurden Funktionen von app.METHOD () oder router.METHOD ().

Dieses Beispiel zeigt einen Middleware-Substack, der GET-Anforderungen an den Pfad / user /: id verarbeitet. "

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')
})
Ula
quelle
0

next () ist das Rückrufargument für die Middleware-Funktion mit req, und res sind die http-Anforderungs- und Antwortargumente für next im folgenden Code.

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

Also ruft next () die übergebene Middleware-Funktion auf. Wenn die aktuelle Middleware-Funktion den Anforderungs- / Antwortzyklus nicht beendet, sollte next () aufgerufen werden. Andernfalls bleibt die Anforderung hängen und es tritt eine Zeitüberschreitung auf.

next () fn muss innerhalb jeder Middleware-Funktion aufgerufen werden, wenn mehrere Middleware-Funktionen an app.use oder app.METHOD übergeben werden. Andernfalls wird die nächste Middleware-Funktion nicht aufgerufen (falls mehr als 1 Middleware-Funktionen übergeben werden). Um das Aufrufen der verbleibenden Middleware-Funktionen zu überspringen, rufen Sie next ('route') innerhalb der Middleware-Funktion auf. Danach sollten keine weiteren Middleware-Funktionen aufgerufen werden. Im folgenden Code wird fn1 und auch fn2 aufgerufen, da next () innerhalb von fn1 aufgerufen wird. Fn3 wird jedoch nicht aufgerufen, da next ('route') innerhalb von fn2 aufgerufen wird.

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();
})
user3022150
quelle