Статья переведена. Ссылка на оригинал
Эта статья представляет собой адаптированный отрывок из книги "Express API Validation Essentials". Она научит вас полноценной стратегии валидации API, которую вы можете начать применять в своих Express-приложениях уже сегодня.
__________________
Документация Express говорит нам, что "приложение Express - это, по сути, серия вызовов функций middleware". На первый взгляд это звучит просто, но, честно говоря, промежуточное ПО может быть весьма запутанным. Вы, вероятно, задавались вопросом:
-
Где правильное место для добавления этого middleware в мое приложение?
-
Когда я должен вызвать функцию обратного вызова
next
, и что произойдет, когда я это сделаю? -
Почему важен порядок использования middleware?
-
Как я могу написать свой собственный код для обработки ошибок?
Паттерн middleware является основополагающим при создании приложений на Express, поэтому вам необходимо хорошо понимать, что такое middleware и как оно работает.
В этой статье мы подробно рассмотрим паттерн промежуточного ПО (middleware). Мы также рассмотрим различные типы middleware Express и то, как эффективно сочетать их при создании приложений.
Шаблон Middleware
В Express Middleware - это определенный стиль функций, которые вы настраиваете для использования вашим приложением. Они могут выполнять любой код, который вам нравится, но обычно они заботятся об обработке входящих запросов, отправке ответов и обработке ошибок. Они являются строительными блоками каждого приложения Express.
Когда вы определяете маршрут в Express, функция-обработчик маршрута, которую вы указываете для этого маршрута, является функцией Middleware:
app.get("/user", function routeHandlerMiddleware(request, response, next) { // execute something});
(Пример 1.1)
Middleware достаточно гибкое. Вы можете указать Express запускать одну и ту же функцию middleware для различных маршрутов, что позволит вам делать такие вещи, как общая проверка для разных конечных точек API.
Помимо написания собственных функций middleware, вы также можете установить стороннее middleware для использования в вашем приложении. В документации Express перечислены некоторые популярные модули middleware. На npm также доступен широкий спектр модулей middleware Express.
Синтаксис Middleware
Вот синтаксис функции middleware:
/** * @param {Object} request - Express request object (commonly named `req`) * @param {Object} response - Express response object (commonly named `res`) * @param {Function} next - Express `next()` function */function middlewareFunction(request, response, next) { // execute something}
(Пример 1.2)
Примечание: Вы могли заметить, что я называю req как request, а res как response. Вы можете называть параметры своих промежуточных функций как угодно, но я предпочитаю использовать более четкие имена переменных, поскольку считаю, что так другим разработчикам легче понять, что делает ваш код, даже если они не знакомы с фреймворком Express.
Когда Express запускает функцию middleware, ей передаются три аргумента:
-
Объект запроса Express (обычно называемый
req
) - это расширенный экземпляр встроенного в Node.js класса http.IncomingMessage. -
Объект ответа Express (обычно называемый
res
) - это расширенный экземпляр встроенного в Node.js класса http.ServerResponse. -
Функция Express
next()
- После того как промежуточная функция выполнит свои задачи, она должна вызвать функциюnext()
, чтобы передать управление следующей промежуточной программе. Если вы передаете ей аргумент, Express принимает его за ошибку. Он пропустит все оставшиеся функции middleware, не обрабатывающие ошибки, и начнет выполнять middleware, которое обрабатывает ошибки.
-
Функции middleware не должны иметь значение
return
. Любое значение, возвращаемое промежуточным ПО, не будет использовано Express.
Два типа Middleware
Обычное промежуточное ПО (middleware)
Большинство функций Middleware, с которыми вы будете работать в приложении Express, являются тем, что я называю "простым" промежуточным ПО (в документации Express нет специального термина для них). Они выглядят как функция, определенная в приведенном выше примере синтаксиса middleware (пример 1.2).
Вот пример простой функции middleware:
function plainMiddlewareFunction(request, response, next) { console.log(`The request method is ${request.method}`); /** * Ensure the next middleware function is called. */ next();}
(Пример 1.3)
Middleware для обработки ошибок
-
Разница между middleware для обработки ошибок и обычным middleware заключается в том, что функции middleware для обработки ошибок задают четыре параметра вместо трех, т.е. (error, request, response, next).
Вот пример функции middleware для обработки ошибок:
function errorHandlingMiddlewareFunction(error, request, response, next) { console.log(error.message); /** * Ensure the next error handling middleware is called. */ next(error);}
(Пример 1.4)
Эта промежуточная функция обработки ошибок будет выполнена,
когда другая промежуточная функция вызовет функцию
next()
с объектом ошибки, например.
function anotherMiddlewareFunction(request, response, next) { const error = new Error("Something is wrong"); /** * This will cause Express to start executing error * handling middleware. */ next(error);}
(Пример 1.5)
Использование middleware
Порядок настройки middleware очень важен. Вы можете применить их на трех различных уровнях в вашем приложении:
-
Уровень маршрута
-
Уровень маршрутизатора
-
Уровень приложения
Если вы хотите, чтобы маршрут (или маршруты) обрабатывал ошибки, которые он вызывает, с помощью middleware для обработки ошибок, вы должны добавить его после определения маршрута.
Давайте рассмотрим, как выглядит настройка middleware на каждом уровне.
На уровне маршрута
Это самый конкретный уровень: любое промежуточное ПО, которое вы настроите на уровне маршрута, будет работать только для этого определенного маршрута.
app.get("/", someMiddleware, routeHandlerMiddleware, errorHandlerMiddleware);
(Пример 1.6)
На уровне маршрутизатора
Express позволяет создавать объекты Router. Они позволяют вам ограничить использование middleware определенным набором маршрутов. Если вы хотите, чтобы одно и то же middleware выполнялось для нескольких маршрутов, а не для всех, то такие объекты могут быть очень полезны.
import express from "express";const router = express.Router();router.use(someMiddleware);router.post("/user", createUserRouteHandler);router.get("/user/:user_id", getUserRouteHandler);router.put("/user/:user_id", updateUserRouteHandler);router.delete("/user/:user_id", deleteUserRouteHandler);router.use(errorHandlerMiddleware);
(Пример 1.7)
На уровне приложения
Это наименее специфический уровень. Любое промежуточное ПО, настроенное на этом уровне, будет запущено для всех маршрутов.
app.use(someMiddleware);// define routesapp.use(errorHandlerMiddleware);
(Пример 1.8)
Технически вы можете определить несколько маршрутов, вызвать
app.use(someMiddleware)
, затем определить несколько
других маршрутов, для которых вы хотите запустить
someMiddleware
. Я не рекомендую такой подход,
поскольку он приводит к запутанной и трудноотлаживаемой структуре
приложения.
Вы должны настраивать middleware на уровне приложения только в случае крайней необходимости, а именно, если его действительно нужно запускать для каждого маршрута в вашем приложении. Каждая функция middleware, независимо от того, насколько она мала, требует определенного времени для выполнения. Чем больше функций middleware необходимо запустить для маршрута, тем медленнее будут выполняться запросы к этому маршруту. Это действительно увеличивается по мере роста вашего приложения и конфигурации с большим количеством middleware. Старайтесь по возможности ограничивать middleware уровнями маршрута или маршрутизатора.
Подведение итогов
В этой статье мы узнали о шаблоне middleware в Express. Мы также узнали о различных типах middleware и о том, как их можно комбинировать при создании приложения на Express.
Если вы хотите прочитать больше о middleware, в документации Express есть несколько руководств:
__________________
Эта статья представляет собой адаптированный отрывок из книги "Express API Validation Essentials". Она научит вас полной стратегии валидации API, которую вы можете начать применять в своих Express-приложениях уже сегодня.
__________________
Все коды на изображениях для копирования доступны здесь.
Статья переведена в преддверии старта курса "Node.js Developer". Всех, кто желает подробнее узнать о курсе и процессе обучения, приглашаем записаться на Demo Day курса, который пройдет 28 июня.
Статья переведена. Ссылка на оригинал