【问题标题】:Is modifying the request object in express.js bad practice?在 express.js 中修改请求对象是不好的做法吗?
【发布时间】:2022-01-13 18:24:01
【问题描述】:

我加入了一个小型开发团队来创业。我们甚至还没有推出。我收到了一个用 node/express 编写的后端服务。除了小型宠物项目,我还没有使用过这项技术。我正在考虑实现一个样式指南,以保持代码的一致性,目标是在其他后端服务中也实现这一点。

这让我想到了 Airbnb 风格指南。这部分突然出现在我身上。 Never mutate parameters

// bad
function f1(obj) {
  obj.key = 1;
}

// good
function f2(obj) {
  const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
}

在 express 中,通常有这样定义的控制器:

async function someController(req, res, next) {

  // I've seen similar code to this
  req.someNewProp = "Some new value."

  res.status(200).json({"someJSONKey":"someJSONVal"});
}

中间件通常是这样定义的:

// Route
router.get('/endpoint', function1, function2)

async function function1(req, res, next) {

  // I've seen similar code to this
  req.someNewProp = "Some new value."

  // Pass req and res to function2
  next();
}

我注意到req 对象在被传递时被修改了很多。数据在中间件和其他函数中被添加到这个对象,因为它在返回响应之前被传递。编写代码的原始开发人员将其称为“将事物保持在请求范围内”。但这似乎直接与风格指南中的一个要点相矛盾,让我怀疑这是否是不好的做法。

所以现在的问题是,是否有一种“更好”或更广泛接受的方式来跟踪请求上下文中的事物,而不会改变原始请求对象?有哪些方法可以做到这一点?

【问题讨论】:

  • 该建议主要适用于表示程序状态的对象。如果只是将参数打包成函数的一种方式,一般来说问题不大。
  • req 是唯一可以默认存储请求相关人员的地方。当然,您可以为每个请求分配其自己的唯一标识符(但您再次需要将其存储在 req 中)并使用它将所有与请求相关的信息存储在其他地方。但是这样一来,您将需要为这些记录添加过期时间。所以总而言之修改req也不错
  • Airbnb 是一个风格指南,即一个固执己见的 linter,我不会碰它,因为它强制使用分号(此外,在其不使用分号的好/坏示例中,它使用内联异步 IIFE,即本身就是不好的做法)ewww,以基于意见的方式结束
  • @LawrenceCherone 风格指南是我掉进兔子洞的原因。我更感兴趣的是直接修改请求是否被认为是不好的做法以及有哪些替代方法。
  • Express 没有简单的替代方案。中间件需要将其结果传递给稍后处理的请求处理程序,req 对象就是这样做的方法。 Express 是专门以这种方式设计的,它希望您在 req 对象上添加/修改属性。这是其设计的核心。在这种情况下,我会忽略 airbnb 指南的建议。请注意,这些是指南,而不是规则,这是有原因的——它们并不普遍适用于所有情况。这是不适用的情况之一。

标签: javascript node.js express


【解决方案1】:

Express 通过将请求/响应处理变量添加为res.locals 的属性,为应用程序提供了一个命名空间来存储它们。这似乎比将非标准属性附加到请求或响应对象本身更好。

以类似的方式,全局应用程序变量可以存储为app.locals的属性

不幸的是,似乎没有为router 实例定义locals 属性。我在res.locals 中放置了对全局路由器实例选项的引用,作为我编写的路由中的第一个中间件步骤,但这是我的选择。

在处理过程中确实可能需要更改请求属性,例如req.path,但这不是不惜一切代价避免的事情。例如,Express 提供了req.originalURL,因此您可以在需要时重新计算路径组件经过深思熟虑的设计

您可能会发现 Express 的使用变得更加有趣 - 我最近才知道并将 error 对象参数传递给 next 函数。至于帖子中的 Airbnb 指南引述:一句话令人印象深刻!帖子中引用的“好”和“坏”代码不做同样的事情

【讨论】:

    【解决方案2】:

    这不是一个坏习惯,这就是 express 中中间件背后的想法,简单来说,中间件是可以修改请求和响应对象甚至决定请求流继续还是终止的函数。但是,您必须小心,不要在预先存在的属性中设置值,否则您可能会有一些奇怪的行为,而且如果您要存储在请求中的信息很大,您可以考虑其他策略实例将信息作为 Redis 存储在内存数据库中。

    【讨论】:

      【解决方案3】:

      查看 express 文档后,我在中间件部分发现了这一点:

      中间件函数可以执行以下任务:

      1. 执行任何代码。
      2. 更改请求和响应对象。
      3. 结束请求-响应周期。
      4. 调用堆栈中的下一个中间件函数。

      Middleware Docs

      所以可以肯定地说,如果文档明确说我们可以修改中间件中的 req 和 response 对象,这可能是一个不错的做法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-06
        • 1970-01-01
        • 2023-03-19
        • 2014-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        相关资源
        最近更新 更多