384 Stimmen

Wofür wird der Parameter "next" in Express verwendet?

Angenommen, Sie haben einen einfachen Codeblock wie diesen:

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

Diese Funktion hat zwei Parameter, req y res , die die Anfrage- bzw. Antwortobjekte darstellen.

Auf der anderen Seite gibt es andere Funktionen mit einem dritten Parameter namens next . Schauen wir uns zum Beispiel den folgenden Code an:

app.get('/users/:id?', function(req, res, next){ // Why do we need next?
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); // What is this doing?
    }
});

Ich kann nicht verstehen, was der Sinn von next() ist oder warum es verwendet wird. In diesem Beispiel, wenn id nicht existiert, was ist dann next tatsächlich tun?

313voto

Asherah Punkte 18163

Er übergibt die Kontrolle an den nächsten passend zu Route. In dem von Ihnen genannten Beispiel könnten Sie den Benutzer in der Datenbank nachschlagen, wenn ein id gegeben wurde, und weisen Sie es req.user .

Im Folgenden könnten Sie eine Route wie die folgende haben:

app.get('/users', function(req, res) {
  // check for and maybe do something with req.user
});

Da /users/123 zuerst mit der Route in Ihrem Beispiel übereinstimmt, wird diese zuerst den Benutzer 123 ; dann /users mit dem Ergebnis etwas anfangen kann.

Strecken-Middleware ist meiner Meinung nach jedoch ein flexibleres und leistungsfähigeres Werkzeug, da es nicht auf ein bestimmtes URI-Schema oder eine bestimmte Reihenfolge der Routen angewiesen ist. Ich wäre geneigt, das gezeigte Beispiel wie folgt zu modellieren, unter der Annahme einer Users Modell mit einer asynchronen findOne() :

function loadUser(req, res, next) {
  if (req.params.userId) {
    Users.findOne({ id: req.params.userId }, function(err, user) {
      if (err) {
        next(new Error("Couldn't find user: " + err));
        return;
      }

      req.user = user;
      next();
    });
  } else {
    next();
  }
}

// ...

app.get('/user/:userId', loadUser, function(req, res) {
  // do something with req.user
});

app.get('/users/:userId?', loadUser, function(req, res) {
  // if req.user was set, it's because userId was specified (and we found the user).
});

// Pretend there's a "loadItem()" which operates similarly, but with itemId.
app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
  req.user.items.append(req.item.name);
});

Die Möglichkeit, den Fluss auf diese Weise zu kontrollieren, ist ziemlich praktisch. Sie möchten vielleicht, dass bestimmte Seiten nur für Benutzer mit einer Admin-Flagge verfügbar sind:

/**
 * Only allows the page to be accessed if the user is an admin.
 * Requires use of `loadUser` middleware.
 */
function requireAdmin(req, res, next) {
  if (!req.user || !req.user.admin) {
    next(new Error("Permission denied."));
    return;
  }

  next();
}

app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
  res.send('blahblahblah');
});

Ich hoffe, das hat Sie inspiriert!

126voto

rajesk Punkte 1357

Ich hatte auch Probleme, next() zu verstehen, aber geholfen

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

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write("Hello");
    next(); //remove this and see what happens 
});

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write(" World !!!");
    httpResponse.end();
});

app.listen(8080);

108voto

Mav55 Punkte 3850

Vor dem Verstehen next müssen Sie eine kleine Vorstellung vom Request-Response-Zyklus in Node haben, wenn auch nicht sehr detailliert. Er beginnt damit, dass Sie eine HTTP-Anfrage für eine bestimmte Ressource stellen, und endet, wenn Sie eine Antwort an den Benutzer zurücksenden, d.h. wenn Sie auf etwas wie res.send('Hello World') stoßen;

Schauen wir uns ein sehr einfaches Beispiel an.

app.get('/hello', function (req, res, next) {
  res.send('USER')
})

Hier brauchen wir next() nicht, denn resp.send beendet den Zyklus und übergibt die Kontrolle zurück an die Route Middleware.

Schauen wir uns nun ein anderes Beispiel an.

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

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

Hier haben wir 2 Middleware-Funktionen für denselben Pfad. Aber Sie werden immer die Antwort von der ersten Funktion erhalten. Denn diese wird zuerst in den Middleware-Stack eingebunden und res.send beendet den Zyklus.

Was aber, wenn wir nicht immer die Antwort "Hello World !!!!" zurückhaben wollen? Unter bestimmten Bedingungen möchten wir vielleicht die Antwort "Hello Planet !!!!". Ändern wir den obigen Code und sehen wir, was passiert.

app.get('/hello', function (req, res, next) {
  if(some condition){
    next();
    return;
  }
  res.send("Hello World !!!!");  
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

Was ist das next hier zu tun. Und ja, Sie könnten Gusses haben. Die erste Middleware-Funktion wird übersprungen, wenn die Bedingung wahr ist, und die nächste Middleware-Funktion wird aufgerufen, und Sie erhalten die "Hello Planet !!!!" Antwort.

Übergeben Sie also die Kontrolle an die nächste Funktion im Middleware-Stack.

Was ist, wenn die erste Middleware-Funktion keine Antwort zurücksendet, aber ein Stück Logik ausführt und Sie dann die Antwort von der zweiten Middleware-Funktion zurückbekommen?

Etwa wie folgt:-

app.get('/hello', function (req, res, next) {
  // Your piece of logic
  next();
});

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

In diesem Fall müssen die beiden Middleware-Funktionen aufgerufen werden. Der einzige Weg, die zweite Middleware-Funktion zu erreichen, ist also der Aufruf von next();

Was ist, wenn Sie nicht zum nächsten Termin anrufen? Erwarten Sie nicht, dass die zweite Middleware-Funktion automatisch aufgerufen wird. Nach dem Aufruf der ersten Funktion wird Ihre Anfrage in der Warteschleife hängen bleiben. Die zweite Funktion wird nie aufgerufen und Sie erhalten keine Antwort zurück.

20voto

Ronique Ricketts Punkte 270

Next wird verwendet, um die Kontrolle an die nächste Middleware-Funktion zu übergeben. Ist dies nicht der Fall, bleibt die Anfrage hängen oder offen.

4voto

Vadi Punkte 2899

Ein wenig Interna hier. Der Hauptzweck von express app handle Funktion ist es, eine Antwort an den Client zu senden und die request-response cycle . Und die Beendigung dieses Zyklus kann durch eine der folgenden Maßnahmen erfolgen response methods (z.B. res.end(), res.json(), usw.). Das heißt, wenn eine Middleware oder route handler führt einige Aktionen aus, ruft dann aber nicht eine der response methods oder die Kontrolle an den nächsten Handler oder die nächste Middleware weitergeben, wird die request-response cycle wird nicht beendet. Aber was die next hängt davon ab, wo und wie sie aufgerufen wird.

Zur Verwaltung verschiedener Aufgaben (Router, Middlewares) express erstellt stacks . Sie sehen aus wie ein queue der tasks . Jede router y route erstellt seine eigene stack de tasks ;

En use Methode der express app schiebt task ( middleware Funktion) zum stack der router . Die app.get , app.post usw. wird eine separate route (mit eigenem stack und schiebt dazu den eigentlichen handlers der route ) im router und schiebt dann zum router verpackt in einer Funktion, die route Bearbeiter. Das heißt, wenn ein route wird in der Datei router stack etwas wie route task (Wrapper-Funktion) mit subtasks geschoben.

// pushes task to the router stack
app.use((req, res, next) => {
    console.log('log request');
    next();
});

// creates route, route stack, 
// pushes tasks to the route stack,
// wraps tasks in a function (another task)
// pushes wrapper function to the
// router stack
app.get('/', (req, res, next) => {
    res.send('Hello World');
});

Als route hat seine eigene stack aufrufen next ohne die Argumente bringt uns nur zum nächsten Handler der route :

app.get('/', 
    (req, res, next) => {
        console.log('first handler');
        // passes the control to the second handler
        next();
    },
    (req, res, next) => {
        console.log('second handler');
        res.send('Hello World');
    }
);

Aufruf von next innerhalb einer middleware ( express empfiehlt, sich zu bewerben use Verfahren zur Montage eines middleware ) bringt uns zum nächsten route o middleware der router Ursache middleware (wenn er montiert ist) in den router stack .

next akzeptiert verschiedene Argumente. Jedes Argument, das nicht 'route' o 'router' wird als Fehler behandelt und an den error middleware die nach allen Routen eingebaut werden müssen und vier Argumente haben:

// error handling middleware
app.use((error, req, res, next) => {
    res.status(error.status || 500);
    res.send(error.message || 'Server internal error');
});

Zeichenfolge 'route' als Argument für next überspringt alle verbleibenden route handlers und bringt uns die nächste route der router :

app.get('/', 
    (req, res, next) => {
        console.log('first handler');
        // passes control to the next route
        next('route');
    },
    (req, res, next) => {
        // this handler will be skipped
        next();
    }
);

app.get('/',
    (req, res, next) => {
        // this route will be called at the end
        res.send('Hello World');
    }
);

Zeichenfolge 'router' als Argument für next bringt uns raus aus der aktuellen router :

// router 'one'
app.get('/', 
    (req, res, next) => {
        console.log('first handler');
        // passes control to the next router
        next('router');
    },
    (req, res, next) => {
        // this handler will be skipped
        next();
    }
);

// router 'two'
app.get('/',
    (req, res, next) => {
        // this route will be called at the end
        res.send('Hello World');
    }
);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X