简体   繁体   中英

Use an array of middlewares at express.js

I'm trying to use an array of middlewares. Well, more like a combination of function names and arrays.

Instead of having:

router.post('/editPassword', validate, changePassword, sendConfirmation);

I would like to have something like:

router.post('/editPassword', validate, [changePassword, sendConfirmation] ); 

That would look like:

router.post('/editPassword', validate, doAction ); 

Where doAction would be an array like this:

var doAction = [
   //equivalent of changePassword
   function(req, res, next){
      //whatever
      next();
   },

   //equivalent to the previous sendConfirmation
   function(req, res, next){
      //whatever
   }
]

But it seems it is failing and going back to the validate step after the next() within the first function in doAction .

I'm looking for a way to simplify the middleware chaining including some middleware steps under the same name.

I assume the reason you wanted it to look that way is not only for it to appear presentable, but also to be able to reuse the other middleware. In that case, you can create a middleware which runs all other middlewares to do the check for you, and only calls the next function if all validations succeed.

var express = require('express');
var app = express();

function middleware1(req, res, next) {
    if(req.query.num >= 1) {
        next();
    } else {
        res.json({message: "failed validation 1"});
    }
}

function middleware2(req, res, next) {
    if(req.query.num >= 2) {
        next();
    } else {
        res.json({message: "failed validation 2"});
    }
}

function middleware3(req, res, next) {
    if(req.query.num >= 3) {
        next();
    } else {
        res.json({message: "failed validation 3"});
    }
}

function combination(req, res, next) {
    middleware1(req, res, function () {
        middleware2(req, res, function () {
            middleware3(req, res, function () {
                next();
            })
        })
    })
}


app.get('/', combination, function (req, res) {
  res.send('Passed All Validation!');
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

You can test this app by running it then viewing http://localhost:3000/?num=3 , changing the value 3 to a lower number, or removing the num parameter.

I'm not sure if this is the proper way to do it, but this is how I've handled my other projects. Let me know what you think.

note : see comments for use case. @robertklep may have a better solution depending on how you want to use middlewares

Latest version of Express can handle this:

function logOriginalUrl (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}

function logMethod (req, res, next) {
  console.log('Request Type:', req.method)
  next()
}

var logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, function (req, res, next) {
  res.send('User Info')
})

You can review more from this link

Just search a little more ^^ : Less ugly and more understandable than previous answer

https://github.com/blakeembrey/compose-middleware

Be careful that you're not doing (the equivalent of) this in your validate middleware:

function middleware(req, res, next) {
  if (someCondition) {
    console.log('some condition is true');
    next();
  }
  console.log('some condition is false');
  res.status(400).end();
}

The intention here is that after calling next the rest of the code isn't executed, but it will. There's nothing really special about next , so when you call it, after it returns the middleware code continues to run (causing both "some condition is true" and "some condition is false" to be logged).

That's why you often see this:

  if (someCondition) {
    console.log('some condition is true');
    return next();
    // Or, alternatively:
    // next();
    // return;
  }

The return causes the middleware function to return after calling next , so the rest of the code in the function won't be executed.

This functionality is already built into express as an array or middleware:

let combined = express.Router()
    .use(
        [
            middleware1,
            middleware2,
            middleware3,
        ],
    );
let combined = express.Router()
    .use(
        middleware1,
        middleware2,
        middleware3,
    );

Full Example

"use strict";

let Http = require("http");
let Express = require("express");

let server = Express();
let app = Express.Router();
let combined = Express.Router();

combined.use(
    function (req, res, next) {
        console.log("huzzah!");
        next();
    },
    function (req, res, next) {
        res.json({ success: true });
    }
);

function middleware0(req, res, next) {
    console.log('ground zero');
    next();
}

app.get("/combined", middleware0, combined);
server.use("/", app);

Http.createServer(server).listen(3000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM