8

I want to move a series of app.use() calls into its own module. The easiest way to encapsulate this is to expose a function(app) in the exports, but I feel that handing over the app object is too much of an opaque interface.

I would like to expose a middleware to be app.use()'d from outside the module. I need to chain/compose the middlewares used internally.

Is there a stylish way of doing this, or an alternative? What's the easiest way of going about it? Anything I should avoid?

4

3 回答 3

15

This answer is a little late, but here it goes anyway...

// composedMiddleware.js
const express = require('express')
const ware1 = (req, res, next)=>{...}
const ware2 = (req, res, next)=>{...}
const router = express.Router()
router.use(ware1)
router.use(ware2)
export default router

// app.js
const composedMiddleWare = require('./composedMiddleware.js')
app.get('/something', (req, res, next)=>{...})
app.get('/something', composedMiddleWare)

If the code isn't self-explanatory, then just note that routers are also middleware. Or, to put it more precisely, "a router behaves like middleware itself, so you can use it as an argument to app.use()" ref.

于 2018-09-01T16:11:07.727 回答
2

Glancing through the code for Express (and Connect, on which it is based), it appears that calling use on a piece of middleware does not notify anything in any way, so there's really no way to compose things ahead of time without passing in app.

You could, however, do the composition at run time, e.g. the first time your middleware is called, compose some functions together and cache/call them.

于 2013-10-13T04:03:18.920 回答
2

Here's my take:

// app.js
...
app.use(require('./middleware')());
...

// middleware.js
var express    = require('express');    
module.exports = function() {
  var middleware = [
    // list of middleware that you want to have performed:
    function mymiddleware(req, res, next) {
      console.log('hello world');
      next();
    },
    express.logger('dev'),
    express.cookieParser(),
    express.static(__dirname)
  ];
  return function(req, res, next) {
    (function iter(i, max) {
      if (i === max) {
        return next();
      }
      middleware[i](req, res, iter.bind(this, i + 1, max));
    })(0, middleware.length);
  };
};

If you need access to the app in your custom middleware, you can access it through req.app or res.app.

于 2013-10-13T06:37:56.033 回答