Що насправді означає проміжне програмне забезпечення та app.use у Expressjs?


228

Практично в кожному додатку Express, який я бачу, є app.useзаява про проміжне програмне забезпечення, але я не знайшов чіткого, короткого пояснення того, що насправді є середнім програмним забезпеченням і що app.useце робить. Навіть самі експрес-документи в цьому відношенні трохи розпливчасті. Чи можете ви мені пояснити ці поняття?


3
Аналогічне питання для довідки (Тхо цей був створений раніше): stackoverflow.com/questions/11321635 / ...
ericsoco

43
^ Га! Ці два питання посилаються один на одного в коментарях.
Джуліан Х. Лам

17
Отже, це круговий довідник.
Стів K

6
Express.js Middleware Demystified Відмінна публікація блогу на цю тему. Це було скопійовано тут раніше, що є плагіатом, звичайно, але оригінальний пост все ще дуже корисний, тому я залишаю посилання тут.
totymedli

1
Я написав статтю про програмне забезпечення express.js. Ось посилання: nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe

Відповіді:


111

проміжне програмне забезпечення

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

Посереднє програмне забезпечення дозволяє визначити степ дій, які ви повинні пройти через. Самі експрес-сервери - це стек середнього рівня.

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

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

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

Шар у стеці проміжного програмного забезпечення - це функція, яка приймає n параметрів (2 для express, req& res) та nextфункцію.

Посереднє програмне забезпечення очікує, що шар зробить деякі обчислення, збільшить параметри і потім викличе next.

Стек нічого не робить, якщо ви не впораєтеся з цим. Express буде обробляти стек щоразу, коли вхідний запит 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); 
});

4
Хм ... це проміжне програмне забезпечення, у цьому випадку ваша власна бібліотека чи частина експресу?
iZ.

5
Класно. Я все ще трохи плутаю app.use()синтаксис. Яке фактичне повернене значення проміжного програмного забезпечення та що useз ним робиться?
iZ.

9
@iZ використання додає його до стеку. Потім кожен запит проходить через стек.
Райнос

7
@Raynos, посилання на ваш проект "проміжне програмне забезпечення" порушено.
Лі

1
@Raynos, але я бачу, що середнє програмне забезпечення все ще використовується в Express? що ти маєш на увазі нульовий?
Тімо Хуовінен

60

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

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


33

Я додаю пізню відповідь, щоб додати щось, що не було зазначено в попередніх відповідях.

На сьогоднішній день повинно бути зрозуміло, що середнє програмне забезпечення / функція (и) виконується між запитом клієнта та відповіддю сервера . Найпоширенішими функціональними можливостями середнього програмного забезпечення є керування помилками, взаємодія бази даних, отримання інформації зі статичних файлів або інших ресурсів. Для переміщення на стеку середнього програмного забезпечення слід викликати наступний зворотний дзвінок, ви можете побачити його в кінці функції середнього програмного забезпечення, щоб перейти до наступного кроку в потоці.

Ви можете використовувати 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, де середнє програмне забезпечення отримує потоки 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
    });
});

2
Я шукав відповідь на те, чи підтримує Express.js підтримку встановлення проміжного програмного забезпечення на основі маршруту (НЕ на маршрутизаторі)? Здається, ви це показали у своїй відповіді.
Сельчук

Чи можете ви пояснити свій приклад вище? Як можна передати стільки функцій в app.get (...) і в якому порядку вони називаються?
Таннер Саммерс

2
Привіт @TannerSummers, .get()метод бере 3 типи аргументів: перший, останній та середній. Внутрішньо він визначає, чи є більше аргументів, ніж 2, і використовує ті (середні) як функції середнього програмного забезпечення, викликаючи їх зліва направо.
Серхіо

22

Експрес- гід має досить акуратну відповідь на ваше запитання, настійно рекомендую прочитати це, я розміщую короткий фрагмент посібника, керівництво досить добре.

Написання проміжного програмного забезпечення для використання в програмах Express

Огляд

Функції середнього програмного забезпечення - це функції, які мають доступ до об'єкта запиту ( req ), об'єкта відповіді ( res ) та наступної функції в циклі запиту-відповіді програми. Наступна функція - це функція в маршрутизаторі Express, яка при виклику виконує проміжне програмне забезпечення, наступне за поточним середнім програмним забезпеченням.

Функції середнього програмного забезпечення можуть виконувати такі завдання:

  • Виконайте будь-який код.
  • Внесіть зміни до запиту та об’єктів відповіді.
  • Закінчіть цикл відповіді на запит.
  • Викличте наступне проміжне програмне забезпечення у стеку.

Якщо поточна функція середнього програмного забезпечення не закінчує цикл відповіді на запит, вона повинна зателефонувати next (), щоб передати управління наступній функції середнього програмного забезпечення. В іншому випадку запит буде залишено висить.

введіть тут опис зображення

Приклад

Ось приклад простої програми «Hello World» Express. У решті цієї статті буде визначено та додано до програми дві проміжні програми: одна під назвою myLogger, яка друкує просте повідомлення журналу, а інша під назвою requestTime 1, що відображає часову позначку HTTP-запиту.

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

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

app.listen(3000)   

Посередня функція myLogger

Ось простий приклад функції середнього програмного забезпечення під назвою "myLogger". Ця функція просто друкує "УВІЙТИ", коли через нього проходить запит до програми. Функція проміжного програмного забезпечення призначена змінній з назвою myLogger.

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

Помітьте виклик вище до наступного () . Виклик цієї функції викликає наступну функцію програмного забезпечення в додатку. Наступна () функція не є частиною Node.js або експрес API, але це третій аргумент , який передається функції проміжного програмного забезпечення . Наступна () функція може бути названа що завгодно, але за згодою вона завжди називається «поруч». Щоб уникнути плутанини, завжди використовуйте цю умову.

Щоб завантажити функцію проміжного програмного забезпечення, зателефонуйте до app.use () , вказавши функцію проміжного програмного забезпечення. Наприклад, наступний код завантажує функцію проміжного програм myLogger перед маршрутом до кореневого шляху (/).

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)

Кожен раз, коли програма отримує запит, вона друкує повідомлення «ВІДПОВІДАЄТЬСЯ» на термінал.

Порядок завантаження середнього програмного забезпечення важливий: спочатку завантажуються функції середнього програмного забезпечення, які завантажуються спочатку.

Якщо мійLogger завантажується після маршруту до кореневого шляху, запит ніколи не надходить до нього, і додаток не друкує "LOGGED", оскільки обробник маршруту кореневого шляху припиняє цикл запиту-відповіді.

Функція посередництва myLogger просто друкує повідомлення, після чого передає запит наступній функції середнього програмного забезпечення в стеку, викликаючи функцію next () .


  1. Ця публікація міститиме лише програмне забезпечення myLogger, для подальшої публікації ви можете ознайомитись із оригінальним посібником для експресів тут .


1
Дуже приємне пояснення.
Драмбег

Він доступний на експрес-сайті тут expressjs.com/en/guide/writing-middleware.html , це дійсно добре. Цікаво, чому поки ніхто про це не згадував.
Сурай Джайн

2
Хороший. Це найясніше пояснення, яке я бачив тут, і так, дивно, що ніхто не посилався на це!
Драмбег

1
Чудово пояснено
Рехан Шиккалгар

Порядок завантаження проміжного програмного забезпечення важливий: спочатку завантажуються функції середнього програмного забезпечення, які завантажуються спочатку. : Це така важлива примітка. Жодної іншої відповіді це не згадує. Для початківця, який працював лише на пітоні, це надзвичайно важливо, оскільки ці речі, можливо, ніколи не стикалися.
Tessaracter

11

===== Дуже дуже просте пояснення =====

Посередні програми часто використовуються в контексті Express.js і є основоположним поняттям для node.js. Коротше кажучи, це в основному функція, яка має доступ до об'єктів запиту та відповіді вашої програми. Те, як я хотів би подумати про це, - це серія "перевірок / попередніх екранів", через яку запит проходить, перш ніж його обробляє програма. Наприклад, Middlewares добре підходить, щоб визначити, чи запит буде аутентифікований перед тим, як перейти до програми та повернути сторінку входу, якщо запит не пройшов автентифікацію або для входу кожного запиту. Доступно багато сторонніх середніх програм, що дозволяють отримати різноманітні функціональні можливості.

Простий приклад середнього програмного забезпечення:

var app = express();
app.use(function(req,res,next)){
    console.log("Request URL - "req.url);
    next();
}

Вищевказаний код буде виконуватися для кожного запиту, який надходить, і записуватиме URL-адресу запиту, наступний () метод по суті дозволяє програмі продовжувати роботу. Якщо наступна () функція не буде викликана, програма не продовжуватиметься і зупиниться при виконанні проміжного програмного забезпечення.

Пара проміжних програм:

  1. Порядок середнього рівня у вашій програмі має значення, оскільки запит проходитиме через кожен у послідовному порядку.
  2. Якщо забути зателефонувати на наступний () метод у вашій функції проміжного програмного забезпечення, можна зупинити обробку вашого запиту.
  3. Будь-яка зміна об'єктів req і res у функції проміжного програмного забезпечення зробить це доступним для інших частин програми, які використовують req та res

1
Велике спасибі! це найкраще пояснення поки що для цього зрозуміти. Питання: я читаю якийсь код з проміжним програмним забезпеченням, але він не дзвонить, next()але return next(). Яка різниця?
KansaiRobot

Дякую багато друга за добрі слова ... ми це робимо, next()тому що ми хочемо, щоб наступне проміжне програмне забезпечення зателефонувало, я не думаю, next()чи return next()має бути якесь значення! І все-таки залежить від того, який код ...
Вайбхав Бачав

7

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

Це як продукт, який проходить через конвеєр, де він модифікується під час руху, поки не буде завершений, оцінений або відхилений.

Посереднє програмне забезпечення очікує, що деяке значення буде працювати (тобто значення параметрів) і, виходячи з певної логіки, середнє програмне забезпечення зателефонує або не зателефонує до наступного середнього програмного забезпечення або відправить відповідь клієнту.

Якщо ви все ще не можете зрозуміти концепцію проміжного програмного забезпечення, вона схожа на схему команд Decorator або Chain команд.


5

Посереднє програмне забезпечення - це підмножина ланцюгових функцій, викликаних рівнем маршрутизації Express js до виклику призначеного користувачем обробника. Функції середнього програмного забезпечення мають повний доступ до об'єктів запиту та відповіді і можуть змінювати будь-який з них.

Ланцюг проміжного програмного забезпечення завжди викликається в тому порядку, в якому він був визначений, тому для вас дуже важливо точно знати, що робить конкретна частина програмного забезпечення.
Як тільки функція посередництва закінчується, вона викликає наступну функцію в ланцюзі, викликаючи наступний аргумент як функцію.
Після того, як вся ланцюг буде виконана, викликається обробник запиту користувача.


1

Прості речі, чоловіче!

Примітка: відповідь стосується вбудованих у середній випадок середнього програмного забезпечення ExpressJS, однак існують різні визначення та випадки використання середнього рівня.

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

Приклад:

Прийняття запитів клієнтів та надання відповідей на них відповідно до їх запитів - це природа технології веб-сервера.

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

Сподіваюся, що це комусь допоможе!


-1

У самому базовому розумінні, якщо я хочу пояснити це так, я дізнаюсь це на курсі експрес-крашів програми traversymedia youtube channel express.
гаразд, середній посуд - це функція, яка виконується після того, як ви дзвоните на свій маршрут таким чином.

var logger = function(req, res, next){
   console.log('logging...');
   next();
}

app.use(logger);

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.