在node.js模型文件中使用res.locals

时间:2018-09-26 11:44:10

标签: node.js express

对于您如何以及为什么设置node.js应用程序以及任何app.use函数如何工作,我总体上一无所知-关于它的教程没有解释任何原因。

无论如何,我在app.js根文件中像这样设置了socket.io,res.locals和index.js。

const sockets = require('./models/socket')(io)

app.use(function (req, res, next) {
    res.locals.user_id = req.session.user_id;
    next();
});

const routes = require('./routes/index');
app.use('/', routes);

我希望能够在socket.js模型中访问res.locals,就像在routes文件夹中找到的index.js中一样。

我猜不出该怎么做。如果有人能够解释我为什么以及为什么不能,那将是一个好处。谢谢!

1 个答案:

答案 0 :(得分:0)

欢迎使用Expressjs,您可能需要进一步研究一些基础知识,它们将有助于解决您的一些困惑。我将对它们进行简要说明,但建议您做进一步的研究。然后,我会在最后回答您的实际问题。

中间件和应用程序使用

Expressjs是基于一切都只是“中间件”的思想而构建的。中间件是作为请求链的一部分运行的功能。请求链本质上是单个客户端请求,然后经过一系列中间件功能,直到它到达链的末尾,通过向客户端返回响应或错误而提前退出。

Express中间件是一个带有以下三个参数的函数。

  • req(请求)-代表客户对您的请求 服务器。
  • res(响应)-代表您将返回的响应 客户。
  • next-一种告诉您当前情况的方法 中间件功能已完成,现在应该调用下一个 中间件。可以将其称为next();的“空”,也可以使用 错误next(new Error());。如果称为空,它将触发 下一个中间件,如果调用时出现错误,则它 将调用第一部分错误中间件。如果next没有在 中间件的末尾,则请求被视为完成,并且 响应对象发送给用户。

app.use是一种设置中间件的方法,这意味着它将针对每个请求运行(除非next()要么由于某种原因未被上一中间件调用,要么被错误地调用)。该中间件将针对任何HTTP请求类型(GETPOSTPUTDELETE等)运行。

app.use可以采用多个参数,对于初学者来说重要的参数是:app.use(func)app.use(path, func)。前者设置“全局”中间件,该中间件无论客户端请求什么端点(URL路径)都运行,而后者(具有特定路径)仅在命中特定路径时运行。即当命中端点“ / hello”时,app.use('/hello', (req, res, next) => { res.send('world'); });将返回“ world”,但是如果客户端请求“ / hi”,则不会。当您碰到任何端点时,app.use((req, res, next) => { res.send('world'); });将返回“世界”。

您可以执行更复杂的操作,但这是将中间件附加到应用程序的基础。它们附加到应用程序的顺序就是它们运行的​​顺序。

还有一件事,这会让您大吃一惊,使用标准const app = express()制作的快速应用程序也可以用作中间件。这意味着您可以创建多个快速应用程序,然后使用app.use将它们安装到单个快速应用程序。这是相当先进的,但是确实可以让您用Express做一些很棒的事情。

为什么不能在socket.io中访问res.locals? (真正的问题)

在中间件处理程序中,您正在设置res.locals.use_id属性。这仅与单个请求一起存在,只要可以将请求传递给其他函数,就可以传递该请求,但在该请求之外不存在。 res实际上是告诉Express响应客户端请求的响应对象,您可以在请求期间设置其属性,但是一旦HTTP请求结束,它就消失了。

Socket.io是一种处理Web套接字请求而不是标准HTTP请求的方法。因此,在标准的快速HTTP请求中,您将无法使用socket.io切换到任何内容的连接,因为该连接是一个短暂的HTTP请求。同样,您将无法以其他方式执行相同操作。

如果您希望在socket.io请求中找到用户ID,则必须在socket.io请求本身中进行操作。

现在,您正在为Express.js请求输入一个中间件,然后调用next()来运行下一个表达中间件,它永远不会跨入Socket.io领域。由于Socket.io可以在Express正在侦听的同一端口上处理请求,因此教程经常将其混淆。因此,您将需要为Express.js请求链和socket.io请求链编写单独的中间件。有一种方法可以编写一次此代码,然后编写适配器以在两个平台上使用,但这不是您在此处尝试做的。

我建议您在使用socket.io之前也只看一下nodejs并表达一段时间,否则您尝试一次学习全部技术是很多尝试并立即全部加入。