node.js - proyecto - ¿Para qué se usa el parámetro "siguiente" en Express?
node js express tutorial (5)
Supongamos que tienes un bloque de código simple como este:
app.get(''/'', function(req, res){
res.send(''Hello World'');
});
Esta función tiene dos parámetros, req
y res
, que representan los objetos de solicitud y respuesta respectivamente.
Por otro lado, hay otras funciones con un tercer parámetro llamado a next
. Por ejemplo, echemos un vistazo al siguiente código:
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?
}
});
No puedo entender cuál es el punto de next()
o por qué se utiliza. En ese ejemplo, si la identificación no existe, ¿qué es lo que está haciendo en realidad?
Antes de comprender a next
, debe tener una pequeña idea del ciclo de Solicitud-Respuesta en el nodo, aunque no mucho en detalle. Comienza haciendo una solicitud HTTP para un recurso en particular y termina cuando envía una respuesta al usuario, es decir, cuando encuentra algo como res.send (''Hello World'');
Echemos un vistazo a un ejemplo muy simple.
app.get(''/hello'', function (req, res, next) {
res.send(''USER'')
})
Aquí no necesitamos next (), porque resp.send finalizará el ciclo y devolverá el control al middleware de ruta.
Ahora echemos un vistazo a otro ejemplo.
app.get(''/hello'', function (req, res, next) {
res.send("Hello World !!!!");
});
app.get(''/hello'', function (req, res, next) {
res.send("Hello Planet !!!!");
});
Aquí tenemos 2 funciones de middleware para la misma ruta. Pero siempre obtendrás la respuesta del primero. Debido a que se monta primero en la pila de middleware y res.send finalizará el ciclo.
Pero qué pasa si no siempre queremos que la respuesta "¡Hola mundo!" Para algunas condiciones podemos querer el "Hello Planet !!!!" respuesta. Vamos a modificar el código anterior y ver qué pasa.
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 !!!!");
});
¿Qué es lo next
hace aquí? Y sí, puede que tengas problemas. Se omitirá la primera función de middleware si la condición es verdadera e invoca la siguiente función de middleware y tendrá el "Hello Planet !!!!"
respuesta.
Entonces, pase el control a la siguiente función en la pila de middleware.
¿Qué pasa si la primera función de middleware no envía ninguna respuesta pero ejecuta una lógica y luego obtiene la respuesta de la segunda función de middleware?
Algo como abajo:
app.get(''/hello'', function (req, res, next) {
// Your piece of logic
next();
});
app.get(''/hello'', function (req, res, next) {
res.send("Hello !!!!");
});
En este caso necesita las dos funciones de middleware para ser invocadas. Por lo tanto, la única forma de llegar a la segunda función de middleware es llamando a next ();
Qué pasa si no haces una llamada al siguiente. No espere que la segunda función de middleware se invoque automáticamente. Después de invocar la primera función, su solicitud quedará colgada. La segunda función nunca se invocará y usted no recuperará la respuesta.
Llamar a esta función invoca la siguiente función de middleware en la aplicación. La función next () no es parte de Node.js o Express API, pero es el tercer argumento que se pasa a la función de middleware. La función next () podría tener cualquier nombre, pero por convención siempre se llama "next".
Next se utiliza para pasar el control a la siguiente función de middleware. De lo contrario la solicitud quedará colgada o abierta.
Pasa el control a la siguiente ruta coincidente . En el ejemplo que da, por ejemplo, puede buscar al usuario en la base de datos si se le dio una id
y asignarlo a req.user
.
A continuación, podría tener una ruta como:
app.get(''/users'', function(req, res) {
// check for and maybe do something with req.user
});
Dado que / users / 123 coincidirá primero con la ruta en su ejemplo, primero se buscará y encontrará al usuario 123
; entonces /users
pueden hacer algo con el resultado de eso.
El middleware de ruta (nota: el enlace está en la documentación 2.x, pero se ha comprobado que funciona en 3.x) es una herramienta más flexible y poderosa, aunque, en mi opinión, ya que no se basa en un esquema de URI en particular orden de ruta. Me sentiría inclinado a modelar el ejemplo que se muestra así, asumiendo que un modelo de Users
con un findOne()
asíncrono:
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);
});
Ser capaz de controlar el flujo de esta manera es bastante útil. Es posible que desee que ciertas páginas solo estén disponibles para usuarios con una marca de administrador:
/**
* 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'');
});
Espero que esto te haya dado algo de inspiración!
También tuve problemas para entender el siguiente (), pero this ayudó
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);