промежуточное ПОШироко используемый в Node.js, он обычно относится к определенному шаблону проектирования, ряду блоков обработки, фильтров и обработчиков в виде функций, соединенных вместе для формирования асинхронной очереди для завершения любой предварительной обработки и постобработки данных.
Его преимущество в том, чтогибкость: С помощью промежуточного программного обеспечения мы получаем плагин с минимальными операциями, самый простой способ расширить новые фильтры и обработчики на существующую систему.
Обычный шаблон промежуточного ПО
В шаблоне промежуточного программного обеспечения самым основным компонентом являетсяменеджер промежуточного программного обеспечения, мы можем использовать его для организации и выполнения функций промежуточного программного обеспечения, как показано ниже:
Для реализации шаблона промежуточного программного обеспечения наиболее важными деталями реализации являются:
- позвонив
use()
функция для регистрации нового промежуточного программного обеспечения.Обычно новое промежуточное программное обеспечение может быть добавлено только в конец высоковольтного пакета, но это не является строго обязательным; - При получении новых данных, которые необходимо обработать, зарегистрированное промежуточное ПО последовательно вызывается в неисполняемом процессе. Каждое промежуточное ПО принимает результат выполнения предыдущего промежуточного ПО в качестве входного значения;
- Каждое промежуточное ПО может остановить дальнейшую обработку данных, просто не вызывая свою функцию уничтожения или передавая ошибку функции обратного вызова. Когда возникает ошибка, она обычно инициирует выполнение другого промежуточного программного обеспечения, которое специализируется на обработке ошибок.
Что касается того, как поступать с передачей данных, то строгих правил на данный момент нет, в общем, есть несколько способов.
- Улучшено добавлением свойств и методов;
- заменить данные результатом некоторой обработки;
- Исходные данные, подлежащие обработке, гарантированно остаются неизменными, а в качестве результата обработки всегда возвращается новая копия.
Специальный метод лечения зависит отменеджер промежуточного программного обеспеченияреализация и тип задач, которые должно выполнять само промежуточное ПО.
Возьмите один изШаблоны проектирования Node.js, второе изданиеРеализация библиотеки обмена сообщениямименеджер промежуточного программного обеспеченияпример:
class ZmqMiddlewareManager {
constructor(socket) {
this.socket = socket;
// 两个列表分别保存两类中间件函数:接受到的信息和发送的信息。
this.inboundMiddleware = [];
this.outboundMiddleware = [];
socket.on('message', message => {
this.executeMiddleware(this.inboundMiddleware, {
data: message
});
});
}
send(data) {
const message = { data };
this.excuteMiddleware(this.outboundMiddleware, message, () => {
this.socket.send(message.data);
});
}
use(middleware) {
if(middleware.inbound) {
this.inboundMiddleware.push(middleware.inbound);
}
if(middleware.outbound) {
this.outboundMiddleware.push(middleware.outbound);
}
}
exucuteMiddleware(middleware, arg, finish) {
function iterator(index) {
if(index === middleware.length) {
return finish && finish();
}
middleware[index].call(this, arg, err => {
if(err) {
return console.log('There was an error: ' + err.message);
}
iterator.call(this, ++index);
});
}
iterator.call(this, 0);
}
}
Далее нужно только создать middleware, соответственно вinbound
а такжеoutbound
Напишите функцию промежуточного программного обеспечения в функции промежуточного программного обеспечения, а затем вызовите ее после выполнения.next()
Достаточно. Например:
const zmqm = new ZmqMiddlewareManager();
zmqm.use({
inbound: function(message, next) {
console.log('input message: ', message.data);
next();
},
outbound: function(message, next) {
console.log('output message: ', message.data);
next();
}
});
Рекламируется Экспресспромежуточное ПОКонцепция похожа, промежуточное ПО Express обычно выглядит так:
function(req, res, next) { ... }
Промежуточное ПО, используемое в Koa2
Модель промежуточного программного обеспечения, показанная ранее, реализована с использованием функций обратного вызова, но теперь есть более модный фреймворк Node.js.Koa2
Реализация промежуточного программного обеспечения несколько отличается от описанной ранее.Koa2
Первоначально использовался шаблон промежуточного программного обеспечения в удаленномES2015
Метод, реализованный генератором в , совместим с функциями обратного вызова,convert
пост генератор иasync
а такжеawait
.
существуетKoa2
Официальная документация дает описание промежуточного программного обеспечения.луковая модель,Как показано ниже:
Из рисунка видно, что первыйinbound
Функция промежуточного программного обеспечения находится вoutbound
Его положили в спину и казнили, так почему? Имея в виду этот вопрос, давайте прочитаемKoa2
исходный код.
существуетkoa/lib/applications.js
, сначала посмотрите на конструктор, а на остальное можете не обращать внимания, ключthis.middleware
,этоinbound
очередь:
constructor() {
super();
this.proxy = false;
this.middleware = [];
this.subdomainOffset = 2;
this.env = process.env.NODE_ENV || 'development';
this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
}
Как и выше, вKoa2
также используется вuse()
Чтобы поставить промежуточное ПО в очередь:
use(fn) {
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
if (isGeneratorFunction(fn)) {
deprecate('Support for generators will be removed in v3. ' +
'See the documentation for examples of how to convert old middleware ' +
'https://github.com/koajs/koa/blob/master/docs/migration.md');
fn = convert(fn);
}
debug('use %s', fn._name || fn.name || '-');
this.middleware.push(fn);
return this;
}
Затем мы смотрим, как фреймворк монитора порта был простым пакетом:
// 封装之前 http.createServer(app.callback()).listen(...)
listen(...args) {
debug('listen');
const server = http.createServer(this.callback());
return server.listen(...args);
}
Ключ к управлению промежуточным ПО лежит вthis.callback()
, взгляните на этот метод:
callback() {
const fn = compose(this.middleware);
if (!this.listenerCount('error')) this.on('error', this.onerror);
const handleRequest = (req, res) => {
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
};
return handleRequest;
}
здесьcompose
Метод на самом делеKoa2
основной модульkoa-compose
(https://github.com/koajs/compose), в этом модуле инкапсулирован метод выполнения промежуточного ПО:
function compose (middleware) {
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
return Promise.reject(err)
}
}
}
}
можно увидеть,compose
Очередь промежуточного ПО выполняется рекурсивноОбход в обратном порядке, который генерируетPromise
цепочка, далее просто нужно позвонитьPromise
Функцию промежуточного программного обеспечения можно выполнить:
handleRequest(ctx, fnMiddleware) {
const res = ctx.res;
res.statusCode = 404;
const onerror = err => ctx.onerror(err);
const handleResponse = () => respond(ctx);
onFinished(res, onerror);
return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
Его можно найти в исходном коде,next()
возвращеноPromise
, поэтому общее промежуточное ПО записывается так:
app.use((ctx, next) => {
const start = new Date();
return next().then(() => {
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
});
Конечно, если вы используетеasync
а такжеawait
также:
app.use((ctx, next) => {
const start = new Date();
await next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
Так как есть многоKoa1
Промежуточное ПО проекта основано на генераторе и должно использоватьkoa-convert
Для выполнения плавного обновления:
const convert = require('koa-convert');
app.use(convert(function *(next) {
const start = new Date();
yield next;
const ms = new Date() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
}));
Наконец, если вы считаете, что статья полезна, пожалуйста, поставьте мне палец вверх! Если вы обнаружите какие-либо ошибки, пожалуйста, не стесняйтесь сообщать о них!