NodeJS 如何将Connect中间件合并为一个中间件?

8ulbf1ek  于 2023-06-05  发布在  Node.js
关注(0)|答案(6)|浏览(177)

我有几个中间件,我想合并成一个中间件。我该怎么做?
例如:

// 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循环之外,还有一个优雅的解决方案。

qkf9rpyu

qkf9rpyu1#

Express接受app.use的阵列,如果您有以下路径:

var middleware = [connect.urlencoded(), connect.json()];
app.use('/', middleware)

但是,如果您想要一个通用的combineMiddleware函数,您可以轻松地构建一个helper,而无需任何额外的库。这基本上利用了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);
      });
    };
  });
}
os8fio9y

os8fio9y2#

如果你喜欢花哨的东西,这里有一个可能的解决方案:

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本身基本上是一个中间件 composer ,所以你可以用你想要的中间件创建另一个connect应用程序:connect.apply(null, middleware).Connect app本身就是一个中间件,唯一的问题是它最后没有next()调用,所以后续的中间件将无法访问。为了解决这个问题,我们需要另一个last中间件,它将调用nextconnect.apply(null, middleware.concat(last))。由于最后只调用next,我们可以使用next.bind(null, null)代替。最后,我们用reqres调用结果函数。

iqih9akk

iqih9akk3#

老问题了,但是对所有使用中间件的东西的需求仍然很频繁,比如connect,express或自定义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);
q5lcpyga

q5lcpyga4#

一个简单和原生的方式,你不需要安装任何东西。

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)
})
u91tlkcl

u91tlkcl5#

如果你想使用图书馆:
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);
70gysomp

70gysomp6#

做一个列表并使用循环。

const connect = require('connect')
const { urlencoded, json } = require('body-parser')

const app = connect()

[ urlencoded(), json() ].forEach(app.use, app)

.forEach的第二个参数用于this,但如果你愿意,你也可以这样做:

[ urlencoded(), json() ].forEach(app.use.bind(app))

相关问题