我想要将一些中间件合并到一个中间件中。我该怎么做?
例如......
// I want to shorten this...
app.use(connect.urlencoded())
app.use(connect.json())
// ...into this:
app.use(combineMiddleware([connect.urlencoded, connect.json]))
// ...without doing this:
app.use(connect.urlencoded()).use(connect.json())
我希望它能够动态运行 - 我不想依赖我使用的中间件。
我觉得除了令人困惑的for
循环之外,还有一个优雅的解决方案。
答案 0 :(得分:13)
Express接受app.use
的数组:
var middleware = [connect.urlencoded(), connect.json()];
app.use('/', middleware)
但是,如果您需要通用combineMiddleware
函数,则可以轻松构建帮助程序而无需任何其他库。这基本上利用了next
只是一个带有可选错误的函数的事实:
/**
* Combine multiple middleware together.
*
* @param {Function[]} mids functions of form:
* function(req, res, next) { ... }
* @return {Function} single combined middleware
*/
function combineMiddleware(mids) {
return mids.reduce(function(a, b) {
return function(req, res, next) {
a(req, res, function(err) {
if (err) {
return next(err);
}
b(req, res, next);
});
};
});
}
答案 1 :(得分:3)
如果你喜欢花哨的东西,这是一个可能的解决方案:
var connect = require('connect')
var app = connect()
function compose(middleware) {
return function (req, res, next) {
connect.apply(null, middleware.concat(next.bind(null, null))).call(null, req, res)
}
}
function a (req, res, next) {
console.log('a')
next()
}
function b (req, res, next) {
console.log('b')
next()
}
app.use(compose([a,b]))
app.use(function (req, res) {
res.end('Hello!')
})
app.listen(3000)
以下是它的作用:compose
函数接受中间件数组并返回组合中间件。 connect
本身基本上是一个中间件编写器,因此您可以使用所需的中间件创建另一个连接应用程序:connect.apply(null, middleware)
。 Connect app本身就是一个中间件,唯一的问题是它最终没有next()
调用,因此后续的中间件将无法访问。要解决这个问题,我们需要另一个last
中间件,它会调用next
:connect.apply(null, middleware.concat(last))
。最后一次只调用next
,我们可以使用next.bind(null, null)
。最后,我们使用req
和res
调用结果函数。
答案 2 :(得分:1)
老问题,但是使用中间件的所有事情仍然需要经常,例如连接,快速或定制的req / res / next模式。
这是一个非常优雅且纯粹功能性的解决方案:
文件 ./ utils / compose-middleware.js :
function compose(middleware) {
if (!middleware.length) {
return function(_req, _res, next) { next(); };
}
var head = middleware[0];
var tail = middleware.slice(1);
return function(req, res, next) {
head(req, res, function(err) {
if (err) return next(err);
compose(tail)(req, res, next);
});
};
}
module.exports = compose;
compose(middlewareList)
的最终结果是一个中间件,它封装了最初提供的整个中间件链。
然后只需导入它并使用如下:
档案 app.js :
var connect = require('connect');
var compose = require('./utils/compose-middleware');
var middleware = compose([
connect.urlencoded(),
connect.json()
]);
var app = connect();
app.use(middleware);
答案 3 :(得分:0)
如果您愿意使用图书馆:
https://www.npmjs.org/package/middleware-flow
var series = require('middleware-flow').series;
var app = require('express')();
app.use(series(mw1, mw2, mw2)); // equivalent to app.use(mw1, mw2, mw3);
答案 4 :(得分:0)
一种简单而原生的方式,您无需安装任何东西。
const {Router} = require('express')
const combinedMiddleware = Router().use([middleware1, middleware2, middleware3])
然后您可以在需要的地方使用 combinedMiddleware
。例如,您可能希望根据某些条件(例如请求属性)为同一路由运行不同的中间件/处理程序集:
app.get('/some-route', (req, res, next) => {
req.query.someParam === 'someValue'
? combinedMiddleware1(req, res, next)
: combinedMiddleware2(req, res, next)
})
答案 5 :(得分:0)
制作一个列表并使用一个循环。
{
using System.Text;
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
System.Text.ASCIIEncoding.ASCIIEncodingSealed asciiEncodingSealed3 = new System.Text.ASCIIEncoding.ASCIIEncoding();
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
System.Text.DecoderReplacementFallback decoderReplacementFallback3 = new System.Text.DecoderReplacementFallback();
System.Text.EncoderReplacementFallback encoderReplacementFallback3 = new System.Text.EncoderReplacementFallback();
this.port = new System.IO.Ports.SerialPort(this.components);
this.SuspendLayout();
//
// port
//
this.port.BaudRate = 9600;
this.port.DataBits = 8;
this.port.DiscardNull = false;
this.port.DtrEnable = false;
asciiEncodingSealed3.DecoderFallback = decoderReplacementFallback3;
asciiEncodingSealed3.EncoderFallback = encoderReplacementFallback3;
this.port.Encoding = asciiEncodingSealed3;
this.port.Handshake = System.IO.Ports.Handshake.None;
this.port.NewLine = "\n";
this.port.Parity = System.IO.Ports.Parity.None;
this.port.ParityReplace = ((byte)(63));
this.port.PortName = "COM6";
this.port.ReadBufferSize = 4096;
this.port.ReadTimeout = -1;
this.port.ReceivedBytesThreshold = 1;
this.port.RtsEnable = false;
this.port.StopBits = System.IO.Ports.StopBits.One;
this.port.WriteBufferSize = 2048;
this.port.WriteTimeout = -1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(484, 461);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
this.ResumeLayout(false);
}
private System.IO.Ports.SerialPort port;
#endregion
}
}```
const connect = require('connect')
const { urlencoded, json } = require('body-parser')
const app = connect()
[ urlencoded(), json() ].forEach(app.use, app)
的第二个参数用于 .forEach
,但如果您愿意,您也可以这样做:
this