【问题标题】:Use an array of middlewares at express.js在 express.js 中使用一组中间件
【发布时间】:2021-08-24 01:52:34
【问题描述】:

我正在尝试使用一系列中间件。嗯,更像是函数名和数组的组合。

而不是:

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

我想要类似的东西:

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

看起来像:

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

doAction 是这样的数组:

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

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

但它似乎失败并在doAction 的第一个函数中的next() 之后返回validate 步骤。

我正在寻找一种方法来简化中间件链接,包括一些同名的中间件步骤。

【问题讨论】:

  • 您是否尝试过将validate 也放入数组中以用于测试目的?
  • 你能解释一下“回到validate这一步”吗?它会再次调用那个中间件吗?
  • 对不起,我的错。它似乎工作得很好。我忘记了next() 之后的退货声明。所以......现在我想知道,为什么要使用 compose-middleware 如果它工作得很好呢?

标签: javascript node.js express


【解决方案1】:

我认为您希望它看起来那样的原因不仅是为了让它看起来像样,而且还能够重用其他中间件。在这种情况下,您可以创建一个中间件来运行所有其他中间件来为您进行检查,并且只有在所有验证都成功时才调用 next 函数。

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!')
})

您可以通过运行此应用然后查看http://localhost:3000/?num=3、将值 3 更改为较小的数字或删除 num 参数来测试它。

我不确定这是否是正确的做法,但这就是我处理其他项目的方式。让我知道你的想法。

注意:请参阅 cmets 了解用例。 @robertklep 可能有更好的解决方案,具体取决于您希望如何使用中间件

【讨论】:

  • combination 在路由处理程序上传递多个中间件函数(无论是否在数组中)时,基本上完成了 Express 在内部已经完成的工作。所以它类似于app.get(..., middleware1, middleware2, middleware3)
  • @robertklep 是的,但是如果您有多个使用该序列的路由并决定稍后更改组合模式,您可以在组合中间件中执行此操作,而不是查找和更改使用它的每条路由.
  • 在这种情况下,这样做:let combination = [ middleware1, middleware2, middleware3 ],并且只使用combination 而不是分别传递三个函数。
  • @robertklep 这就是我之前的想法。我想我的回答只有在您需要比其他中间件提供的更多验证时才有意义。就像使用您无法控制的第三方中间件一样。
【解决方案2】:

多搜索一下^^:比以前的答案不那么难看,更容易理解

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

【讨论】:

  • 刚刚注意到这是我身边的一个错误。所以...现在我想知道,为什么要使用compose-middleware 如果这样就可以了?有什么优势?
  • 优点是可以轻松组合中间件以供重用(例如在 expressjs 项目中:您使用 2 个中间件,它们后面都有另一个中间件,对另一个项目也很有用)。如果 middleware2 失败,您还可以控制调用 next 并且仅在 middleware2 成功时才调用 middleware3)
【解决方案3】:

请注意不要在 validate 中间件中执行(相当于)此操作:

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

这里的意图是在调用next 之后,其余代码不会被执行,但它会。 next 没有什么特别之处,所以当你调用它时,它返回后中间件代码继续运行(导致 "some condition is true""some condition is false" 被记录)。

这就是为什么你经常看到这个:

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

return导致中间件函数在调用next后返回,所以函数中的其余代码不会被执行。

【讨论】:

    【解决方案4】:

    最新版本的 Express 可以处理这个问题:

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

    您可以通过this link查看更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 2013-09-23
      • 2022-12-08
      • 2019-03-31
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多