【问题标题】:Express - better pattern for passing data between middleware functionsExpress - 在中间件函数之间传递数据的更好模式
【发布时间】:2016-03-24 15:33:08
【问题描述】:

我刚刚向 Express 提出了这个问题,我对 StackOverflow 的想法很感兴趣:

https://github.com/strongloop/express/issues/2831

我的问题是,为什么 Express 选择禁止开发人员在中间件函数之间直接传递数据,并且基本上强制您将临时数据分配给请求对象,而我一直认为这很尴尬任务。

更具体一点:

在中间件函数之间传递数据通常涉及到这样做

req.specialData = {}
next();

但是,如果可能的话,它可能会更容易且性能更高(!)

next(null,data);

function mySpecialMiddleWare(req,res,next,data){}

//现在,调用上面的函数

mySpecialMiddleWare(req,res,next, {some:data});

问题是 Express 使用了一种我认为是愚蠢的方法来确定调用是对普通中间件函数还是下一个错误第一个中间件函数,方法是检查是否function.length > 3 或 function.length === 4...

我所说的是否有任何意义?

允许通过中间件函数直接传递数据而不是笨拙地将数据分配给 req 不是更好/更容易/更快/更强吗??

也许 Express 已经具备此功能,而我只是被误导了?

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    我的问题是,为什么 Express 选择禁止开发人员直接在中间件函数之间传递数据,并且基本上强制您将临时数据分配给请求对象,而我一直认为这是一个非常尴尬的分配。

    所以我认为 API 是鼓励大多数中间件模块化、可重用和松散耦合的方式。这意味着通常应该做一些事情,而不必太担心其他中间件可能在它们之前或之后运行。为了实现这一点并创建一个松散兼容的中间件功能生态系统,express 保持 API 相当通用。这有好处也有坏处。但作为对您的第一个问题的直接回答,我想说的是保持界面简单、一致和灵活,并尽量避免严格的顺序依赖关系。

    在您的情况下,中间件之间可能存在隐式依赖关系。另一个常见的例子通常是你的会话中间件有一个隐含的依赖关系,你的 cookie 中间件在它之前运行。可以认为将这些都隐含会产生错误和不必要的故障排除。另一方面,它使应用程序开发人员能够更轻松地混合和匹配可能彼此不了解的中间件。

    事后看来,我认为我和一些快速维护者都会同意,出于语义 API 的原因使用函数 arity(预期参数的数量)对 TJ 来说是一个奇怪且糟糕的选择。我认为如果要重写项目,将定义更明确的 API 来处理错误。

    允许通过中间件函数直接传递数据而不是笨拙地将数据分配给 req 不是更好/更容易/更快/更强吗??

    更好 - 这是非常有争议和基于意见的。它的简单性有很多话要说,证据就是巨大的生态系统和使用。有可用的替代方案,例如 hapi、restify 等,但您可以考虑使用它们。

    更容易 - 可能不会。那里的东西很简单。

    更快 - 可能没有任何意义。不知道为什么您认为您的版本会更快,但最好在您提出此类声明时提供指标。

    更强 - 如果“更强”是指更明确,这可能是正确的,但有些人仍然更喜欢 JavaScript 是有原因的,即使 TypeScript 一直到 Haskell 都存在并且在某种意义上绝对“更强”。

    【讨论】:

    • 谢谢你确实提出了一些好处;我的意思是在愚蠢朋克意义上更快/更强
    • 将这样的临时变量分配给 req 可能会增加内存吗?只是在函数之间传递变量肯定会占用更少的内存。
    • 另外,jerryrig 的一种方法是调用带有 5 个或更多参数的中间件函数,它应该绕过错误中间件,只是将您带入下一个中间件函数 - 也就是说 - 如果Express 不会从下一次调用中剪辑/截断额外的参数。但是不能用next()调用,必须用中间件调用(req,res,next,{},{})
    • 当然。如果中间件模式不合适,请使用好的旧函数。
    • 是的,但我只是希望你能调用 next(null,{}),那太好了。 Express,如果一切顺利,可以为您将该对象放在 req 上,因此上述调用会将对象分配给 req.foo 或其他任何东西......并且如果您可以评论 req 上临时变量的内存增加...... .不确定这是否有效果。
    【解决方案2】:

    Express 所做的可能有一些优势,但是值得注意的是,Express 允许使用 res.locals 在中间件之间传递数据。话虽如此,您的问题启发了我制作这个库。 Expressjs-plus. 有了它,您将能够轻松地在中间件之间传递数据,而无需使用请求或响应对象。

    您可以使用常规的 javascript 函数,例如function(varInResLocals, varInReqParams, callback) 而不是 express 中间件签名。

    这是一个适合您的工作示例。

     var express = require('express');
     var ExpressPlus = require('expressjs-plus').ExpressPlus;
     var app = express();
     // simple handler example
     var userHandler = function(param, paramsArray, req, res){
        if(param !== 'user') return false;
        paramsArray.push("USER WAS FOUND!");
        return true;
    };
    
     // this handler allows you to pass res.locals properties between your middlewares seemingly,
     // it the parameter was found in locals, it attaches it to paramsArray.
     var resLocalsHandler = function(param, paramsArray, req, res){
        if(param in res.locals){
            paramsArray.push(res.locals[param]);
            return true;
        }else return false;
    };
     var appPlus = new ExpressPlus(app, [userHandler, resLocalsHandler], []);
     var regularFunction = function(user, id, cb){
        return cb(null, { response: {user: user, id: id}, status: 200, resLocalsVar: "passVar" });
    };
    
     // resLocalsVar was passed in a previous method
     var regularFunction2 = function(resLocalsVar, user, id, cb){
     // now you can have access to it
        console.log(resLocalsVar);
        return cb(null);
    };
    
     // the responder at the end will use res.locals.status and res.locals.response to issue an HTTP response
     app.use(appPlus.GMV(regularFunction), appPlus.GMV(regularFunction2), appPlus.responder);
    
     // adds error handlers, it will add a default error handler along with the list of error handlers passed
     // in this case, no error handlers were passed
     appPlus.setErrorHandlers();
    
     app.listen(3001, function(){
        console.log('Listening!');
    });    
    

    【讨论】:

      猜你喜欢
      • 2018-12-11
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      • 2018-12-18
      • 1970-01-01
      • 2016-04-20
      • 1970-01-01
      • 2015-06-19
      相关资源
      最近更新 更多