У меня есть экземпляр Express.js и несколько маршрутов, которые я хочу обернуть некоторой функцией. Пример:
const wrapper = (route) => {
return (req, res, next) => {
let result = route(req, res, next);
// do some independent processing
}
};
app.get('/', wrapper((req, res, next) => {
// respond to request somehow
}));
Хотя это прекрасно работает, мне не нравится идея явно называть wrapper
на каждом маршруте или промежуточном программном обеспечении, требующем такой обработки.
Есть ли способ обернуть каждый необходимый маршрут/промежуточное ПО в определенную оболочку (учитывая, что функция- wrapper
может проверять, что этот маршрут/промежуточное программное обеспечение необходимо обернуть) неявно (через расширение Express.js
, исправление обезьяны или какое-то специальное промежуточное ПО)?
ОБНОВИТЬ:
Более солидный пример. Предположим, что я хочу сделать async
функции маршрутизатора. Но я не хочу ломать ошибки в каждой функции маршрута. Поэтому я завершаю их:
const wrapper = func => (req, res, next) => {
const promise = func(req, res, next);
if (promise.catch) {
promise.catch(err => next(err));
}
next();
};
app.get('/one', wrapper(async (req, res, next) => {
// respond to request somehow
}));
app.get('/two', wrapper(async (req, res, next) => {
// respond to request somehow
}));
app.get('/three', wrapper(async (req, res, next) => {
// respond to request somehow
}));
// and so on...
app.use((err, req, res, next) => {
// do something with intercepted error
});
Эта явная wrapper
вокруг всех маршрутов на самом деле является тем, от чего я хочу избавиться.
Это оказалось немного PITA, потому что, в конечном счете, Express не распространяет возвращаемое значение функции обработчика маршрута.
Это то, что я придумал (обезьяна-патч):
const Layer = require('express/lib/router/layer');
const handle_request = Layer.prototype.handle_request;
Layer.prototype.handle_request = function(req, res, next) {
if (! this.isWrapped && this.method) {
let handle = this.handle;
this.handle = function(req, res, next) { // this is basically your wrapper
let result = handle.apply(this, arguments);
// do some independent processing
return result;
};
this.isWrapped = true;
}
return handle_request.apply(this, arguments);
};
Вероятно, я бы предложил использовать аналогичный подход, например, express-promise-router
, который реализует замену для Express ' Router
. Однако это не подразумевается.
Почему бы просто не использовать next()?
Вы можете добавить материал в req как
app.get('/', (req, res, next) => {
req.somestupidfieldthatidontevenknowwhyinamedthisway = 42;
next();
});
app.get('/', (req, res, next) => {
//req.somestupidfieldthatidontevenknowwhyinamedthisway is now accessible as 42
var valueFromPreviousMiddleware = req.somestupidfieldthatidontevenknowwhyinamedthisway;
.....
});
if (result.catch) { ... }
). Очевидно, вы также можете переписать его в служебную функцию, чтобы скрыть кровавые подробности.