¿Qué significan realmente middleware y app.use en Expressjs?

Resuelto iZ. asked hace 13 años • 9 respuestas

Casi todas las aplicaciones Express que veo tienen una app.usedeclaración para middleware, pero no he encontrado una explicación clara y concisa de qué es realmente el middleware y qué app.usehace la declaración. Incluso los propios documentos expresos son un poco vagos al respecto. ¿Puedes explicarme estos conceptos por favor?

iZ. avatar Sep 07 '11 23:09 iZ.
Aceptado

software intermedio

Estoy a medio camino de separar el concepto de middleware en un nuevo proyecto.

El middleware le permite definir una pila de acciones que debe realizar. Los propios servidores Express son una pila de middleware.

// express
var app = express();
// middleware
var stack = middleware();

Luego puede agregar capas a la pila de middleware llamando.use

// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
  next();
});

Una capa en la pila de middleware es una función que toma n parámetros (2 para express, req& res) y una nextfunción.

El middleware espera que la capa haga algunos cálculos, aumente los parámetros y luego llame next.

Una pila no hace nada a menos que la manejes. Express manejará la pila cada vez que se detecte una solicitud HTTP entrante en el servidor. Con el middleware manejas la pila manualmente.

// express, you need to do nothing
// middleware
stack.handle(someData);

Un ejemplo más completo:

var middleware = require("../src/middleware.js");

var stack = middleware(function(data, next) {
    data.foo = data.data*2;
    next();
}, function(data, next) {
    setTimeout(function() {
        data.async = true;
        next();
    }, 100)
}, function(data) {
    console.log(data);
});

stack.handle({
    "data": 42
})

En términos expresos, simplemente define una pila de operaciones que desea que maneje Express para cada solicitud HTTP entrante.

En términos de express (en lugar de conexión), tiene middleware global y middleware específico de ruta. Esto significa que puede adjuntar una pila de middleware a cada solicitud HTTP entrante o solo adjuntarla a solicitudes HTTP que interactúan con una ruta determinada.

Ejemplos avanzados de express y middleware:

// middleware 

var stack = middleware(function(req, res, next) {
    users.getAll(function(err, users) {
        if (err) next(err);
        req.users = users;
        next();  
    });
}, function(req, res, next) {
    posts.getAll(function(err, posts) {
        if (err) next(err);
        req.posts = posts;
        next();
    })
}, function(req, res, next) {
    req.posts.forEach(function(post) {
        post.user = req.users[post.userId];
    });

    res.render("blog/posts", {
        "posts": req.posts
    });
});

var app = express.createServer();

app.get("/posts", function(req, res) {
   stack.handle(req, res); 
});

// express

var app = express.createServer();

app.get("/posts", [
    function(req, res, next) {
        users.getAll(function(err, users) {
            if (err) next(err);
            req.users = users;
            next();  
        });
    }, function(req, res, next) {
        posts.getAll(function(err, posts) {
            if (err) next(err);
            req.posts = posts;
            next();
        })
    }, function(req, res, next) {
        req.posts.forEach(function(post) {
            post.user = req.users[post.userId];
        });

        res.render("blog/posts", {
            "posts": req.posts
        });
    }
], function(req, res) {
   stack.handle(req, res); 
});
Raynos avatar Sep 07 '2011 17:09 Raynos

Después de simplificar las cosas, un servidor web puede verse como una función que recibe una solicitud y genera una respuesta. Entonces, si ve un servidor web como una función, podría organizarlo en varias partes y separarlas en funciones más pequeñas para que la composición de ellas sea la función original.

Los middlewares son funciones más pequeñas que puedes componer con otras y el beneficio obvio es que puedes reutilizarlas.

Barum Rho avatar Sep 07 '2011 17:09 Barum Rho

Agrego una respuesta tardía para agregar algo que no se menciona en las respuestas anteriores.

A estas alturas debería quedar claro que el middleware es una función que se ejecuta entre la solicitud del cliente y la respuesta del servidor . La funcionalidad de middleware más común necesaria es la gestión de errores, la interacción con la base de datos y la obtención de información de archivos estáticos u otros recursos. Para avanzar en la pila de middleware, se debe llamar a la siguiente devolución de llamada; puede verlo al final de la función de middleware para pasar al siguiente paso del flujo.

Puedes usar el app.useenfoque y tener un flujo como este :

var express = require('express'),
    app = express.createServer(),                                                                                                                                                 
    port = 1337;

function middleHandler(req, res, next) {
    console.log("execute middle ware");
    next();
}

app.use(function (req, res, next) {
    console.log("first middle ware");                                                                                                             
    next();
});

app.use(function (req, res, next) {
    console.log("second middle ware");                                                                                                             
    next();
});

app.get('/', middleHandler, function (req, res) {
    console.log("end middleware function");
    res.send("page render finished");
});

app.listen(port);
console.log('start server');

pero también puedes usar otro enfoque y pasar cada middleware como argumentos de función. A continuación se muestra un ejemplo del sitio web de MooTools Nodejs donde el middleware obtiene el flujo de Twitter, Github y Blog antes de responseenviarlo de vuelta al cliente. Observe cómo las funciones se pasan como argumentos en app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. El uso app.getsolo se llamará para solicitudes GET y app.usese llamará para todas las solicitudes.

// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
    org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
    blogData.get(function(err, blog) {
        if (err) next(err);
        res.locals.lastBlogPost = blog.posts[0];
        next();
    });
}

// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
    res.render('index', {
        title: 'MooTools',
        site: 'mootools',
        lastBlogPost: res.locals.lastBlogPost,
        tweetFeed: res.locals.twitter
    });
});
Sergio avatar May 18 '2015 20:05 Sergio

La guía expressjs tiene una respuesta bastante clara a su pregunta. Le recomiendo que la lea. Estoy publicando un breve fragmento de la guía, la guía es bastante buena.

Escribir middleware para usar en aplicaciones Express

Descripción general

Las funciones de middleware son funciones que tienen acceso al objeto de solicitud ( req ), al objeto de respuesta ( res ) y a la siguiente función en el ciclo de solicitud-respuesta de la aplicación. La siguiente función es una función en el enrutador Express que, cuando se invoca, ejecuta el middleware que sucede al middleware actual.

Las funciones de middleware pueden realizar las siguientes tareas:

  • Ejecute cualquier código.
  • Realice cambios en los objetos de solicitud y respuesta.
  • Finalizar el ciclo solicitud-respuesta.
  • Llame al siguiente middleware de la pila.

Si la función de middleware actual no finaliza el ciclo de solicitud-respuesta, debe llamar a next() para pasar el control a la siguiente función de middleware. De lo contrario, la solicitud quedará suspendida.

ingrese la descripción de la imagen aquí

Ejemplo

A continuación se muestra un ejemplo de una sencilla aplicación Express “Hello World”. El resto de este artículo definirá y agregará dos funciones de middleware a la aplicación: una llamada myLogger que imprime un mensaje de registro simple y otra llamada requestTime 1 que muestra la marca de tiempo de la solicitud HTTP.

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

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

app.listen(3000)   

Función de middleware myLogger

A continuación se muestra un ejemplo sencillo de una función de middleware llamada "myLogger". Esta función simplemente imprime "LOGGED" cuando pasa una solicitud a la aplicación. La función de middleware se asigna a una variable denominada myLogger.

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

Observe la llamada anterior a next() . Llamar a esta función invoca la siguiente función de middleware en la aplicación. La función next() no forma 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 denomina "siguiente". Para evitar confusiones, utilice siempre esta convención.

Para cargar la función de middleware, llame a app.use() y especifique la función de middleware. Por ejemplo, el siguiente código carga la función de middleware myLogger antes de la ruta a la ruta raíz (/).

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)

Cada vez que la aplicación recibe una solicitud, imprime el mensaje "LOGGED" en el terminal.

El orden de carga del middleware es importante: las funciones del middleware que se cargan primero también se ejecutan primero.

Si myLogger se carga después de la ruta a la ruta raíz, la solicitud nunca llega y la aplicación no imprime "LOGGED", porque el controlador de ruta de la ruta raíz finaliza el ciclo de solicitud-respuesta.

La función de middleware myLogger simplemente imprime un mensaje y luego pasa la solicitud a la siguiente función de middleware en la pila llamando a la función next() .


  1. Esta publicación solo contendrá el middleware myLogger; para más publicaciones, puede consultar la guía original de expressjs aquí .

Suraj Jain avatar Jan 05 '2018 04:01 Suraj Jain