Что означает промежуточное ПО и app.use в Expressjs?

Почти каждое приложение Express, которое я вижу, имеет инструкцию app.use для промежуточного программного обеспечения, но я не нашел четкого и краткого объяснения того, что такое промежуточное ПО и что делает оператор app.use. Даже сами экспресс-документы немного расплывчаты по этому поводу. Можете ли вы объяснить эти концепции для меня, пожалуйста?

Ответ 1

middleware

Я на полпути разделяю концепцию промежуточного программного обеспечения в новом проекте.

Среднее программное обеспечение позволяет определить стек действий, которые вы должны протекать. Экспресс-серверы представляют собой стек промежуточных продуктов.

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

Затем вы можете добавить слои в стек промежуточного программного обеспечения, вызвав .use

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

Уровень в стеке промежуточного программного обеспечения - это функция, которая принимает n параметров (2 для выражения, req и res) и next.

Middleware ожидает, что слой выполнит некоторые вычисления, увеличит параметры, а затем вызовет next.

Стек ничего не делает, если вы не справитесь с ней. Экспресс обрабатывает стек каждый раз, когда входящий HTTP-запрос попадает на сервер. С помощью промежуточного программного обеспечения вы вручную обрабатываете стек.

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

Более полный пример:

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

В экспресс-терминах вы просто определяете стек операций, которые вы хотите выразить для каждого входящего HTTP-запроса.

В терминах экспресс (а не подключения) у вас есть глобальное промежуточное ПО и специфическое для маршрута промежуточное программное обеспечение. Это означает, что вы можете прикреплять стек промежуточного программного обеспечения к каждому входящему HTTP-запросу или присоединять его только к HTTP-запросам, которые взаимодействуют с определенным маршрутом.

Расширенные примеры экспресс и промежуточного ПО:

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

Ответ 2

После упрощения веб-сервера можно рассматривать как функцию, которая принимает запрос и выводит ответ. Поэтому, если вы рассматриваете веб-сервер как функцию, вы можете организовать его на несколько частей и разделить на более мелкие функции, чтобы их состав был оригинальной.

Middlewares - это меньшие функции, которые вы можете сочинять вместе с другими, и очевидная выгода заключается в том, что вы можете их повторно использовать.

Ответ 3

Я добавляю поздний ответ, чтобы добавить что-то, не упомянутое в предыдущих ответах.

К настоящему моменту должно быть ясно, что промежуточное программное обеспечение - это функции (-ы), выполняемые между запросом клиента и ответом сервера. Наиболее распространенными функциями промежуточного программного обеспечения являются управление ошибками, взаимодействие с базами данных, получение информации из статических файлов или других ресурсов. Чтобы перейти на стек промежуточного программного обеспечения, необходимо вызвать следующий обратный вызов, вы можете увидеть его в конце функции промежуточного программного обеспечения, чтобы перейти к следующему этапу потока.

Вы можете использовать подход app.use и иметь поток как это:

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

но вы также можете использовать другой подход и передавать каждое промежуточное ПО в качестве аргументов функции. Вот пример с сайта MooTools Nodejs, где midleware получает поток Twitter, Github и Blog до отправки response клиенту. Обратите внимание, как функции передаются в качестве аргументов в app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. Использование app.get будет вызываться только для запросов GET, app.use будет вызываться для всех запросов.

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

Ответ 4

Middlewares - это функции, выполняемые в середине после ввода/источника, а затем выводят вывод, который может быть конечным результатом или может использоваться следующим промежуточным программным обеспечением до завершения цикла.

Это похоже на продукт, который проходит через конвейер, где он изменяется, когда он перемещается, пока он не будет завершен, не оценен или не будет отклонен.

Среднее программное обеспечение ожидает некоторого значения для работы (то есть значений параметров) и на основе некоторой логики промежуточное программное обеспечение будет вызывать или не вызывать следующее промежуточное программное обеспечение или отправлять ответ клиенту.

Если вы еще не можете понять концепцию промежуточного программного обеспечения, это похоже на стиль оформления Decorator или Chain.

Ответ 5

Middleware - это подмножество связанных функций, называемых слоем маршрутизации Express js, прежде чем вызывается пользовательский обработчик. Функции промежуточного программного обеспечения имеют полный доступ к объектам запроса и ответа и могут изменять любой из них.

Цепочка промежуточного программного обеспечения всегда вызывается в том порядке, в котором она определена, поэтому вам важно точно знать, что делает конкретная часть промежуточного программного обеспечения.
После завершения функции промежуточного программного обеспечения она вызывает следующую функцию в цепочку, вызывая ее следующий аргумент как функцию.
После того, как полная цепочка будет выполнена, вызывается обработчик запроса пользователя.

Ответ 6

Держите вещи просто, мужчина!

Примечание. ответ относится к встроенным средним корпусам ExpressJS, однако существуют разные определения и варианты использования middlewares.

С моей точки зрения, промежуточное программное обеспечение действует как служебные или вспомогательные функции, но его активация и использование полностью необязательны, используя app.use('path', /* define or use builtin middleware */), которые не хотят от нас писать код для выполнения очень общие задачи, которые необходимы для каждого HTTP-запроса нашего клиента, например обработки файлов cookie, токенов CSRF и..., которые очень распространены в большинстве приложений , поэтому промежуточное программное обеспечение может помочь нам сделать все это для каждого HTTP-запроса нашего клиента в некоторый стек, последовательность или порядок операций затем обеспечивают результат процесса как единую единицу запроса клиента.

Пример:

Принятие запросов клиентов и предоставление обратных ответов на них в соответствии с их запросами - это характер технологии веб-сервера.

Представьте, если мы предоставляем ответ только с "Привет, мир!". текст запроса GET HTTP на наш корневой URI веб-сервера - очень простой сценарий и не нуждается ни в чем другом, но вместо этого, если мы проверяем зарегистрированного пользователя, а затем отвечаем "Привет, Имя пользователя!". требует чего-то большего, чем обычно, в этом случае нам требуется промежуточное программное обеспечение для обработки всех метаданных запроса клиента и предоставления нам идентификационной информации, захваченной с клиентского запроса, тогда в соответствии с этой информацией мы можем однозначно идентифицировать нашего текущего пользователя, и можно ответить на него/ей с некоторыми связанными данными.

Надеюсь, что это поможет кому-то!