我正在尝试为我的后端实现一项服务,允许从代码中的任何位置调用 session 数据,这意味着我想创建一个服务文件,从获取 session 数据的函数中导出值。否则,我只能从同时具有 req: Request 和 res: Response 参数的内部函数获取 session 数据。因此,我基本上尝试将值锁定到可以从项目中的任何位置使用和调用的变量。我的代码现在看起来像这样,但如果我在文件中的其他任何地方使用导出,它只会打印实际的代码(函数)片段,而不是代码内指定的返回值。一般来说,我对 typescript 和 Node 还很陌生,这意味着我可能会在这里犯一些非常愚蠢的错误。
感谢您提前提供的所有帮助! /维克多
import { Request, Response, NextFunction } from "express";
function getUserSessionData(req: Request, res: Response) {
const userData = res.status(200).send(req.session.userData);
return userData;
}
function getUserSessionLang(req: Request, res: Response) {
const userLang = res.status(200).send(req.session.language);
return userLang;
}
function getUserSessionAll(req: Request, res: Response) {
const userAll = res.status(200).send(req.session);
return userAll;
}
module.exports = {
userData: getUserSessionData,
userLang: getUserSessionLang,
userAll: getUserSessionAll
};
我希望它如何工作:
const sessionService = require("./services/sessionService");
function getStuff(req: Request, res: Response, next: NextFunction) {
let redisKey;
if (!req.session.language) {
redisKey = "getStuffEN";
}
else {
redisKey = "getStuff" + sessionService.userLang;
}
console.log(redisKey);
getRedis(redisKey, function success(reply: any) {
res.status(200).json(
JSON.parse(reply)
);
}, function error(err: Error) {
console.log("Something went wrong");
});
}
这就是现在的情况(并且正在工作)
function getStuff(req: Request, res: Response, next: NextFunction) {
let redisKey;
if (!req.session.language) {
redisKey = "getStuffEN";
}
else {
redisKey = "getStuff" + req.session.language;
}
console.log(redisKey);
getRedis(redisKey, function success(reply: any) {
res.status(200).json(
JSON.parse(reply)
);
}, function error(err: Error) {
console.log("Something went wrong");
});
}
我希望它像第一个示例一样工作,因为我的代码中有一些实例,我希望在可能的情况下无需传递 req、res 参数即可访问数据。
最佳答案
首先,对 session 进行简短说明:
- 当用户登录(并且您验证他的凭据,etz)时,您会为该用户启动一个新 session 。
- 您使用的中间件将为该 session 分配一个唯一的 ID,您可以为其分配一些数据。
- ID以 cookie 的形式传输到用户浏览器
- 数据存储在服务器上(根据您的情况存储在 Redis 中)
- 中间件将检查请求中是否包含具有有效 ID 的 session cookie,并执行以下操作:
- 从 Redis 获取给定 ID 的 session -数据
- 使用 Redis 中的数据填充
req.session
对象 - 调用下一条路线
解决这个问题后,有一条建议:不要将 session 数据存储在应用程序内存中。为什么?数据应该仅在用户请求的上下文中相关。您将需要 session 数据来处理请求,但其他情况下则不需要它。
不要将其存储在全局范围内,而是构建处理程序和函数以接受特定的 session 数据作为参数,如下所示:
// handler, after middleware:
const getUserBio = (req, res) => {
const userId = req.session.userId;
const bioData = fetchBio(userId);
res.render("userBio", bioData);
}
// somewhere else in your code
function fetchBio(userId) {
const fullBio = database.fetchBio(userId);
return {
full: fullBio,
excerpt: fullBio.substring(0, 24);
}
}
这有两个重要的优点:
- 您不必将内存中的 session 数据与 Redis 中的 session 数据保持同步
- 这些(几乎)pure functions让你的代码更容易理解
如果您编写的函数完全对其输入参数起作用并且不使用任何全局状态,那么“调用函数的顺序”或“检查数据是否可用”之类的事情就变得无关紧要。调用者负责获取数据,被调用者负责使用它。
在此基础上扩展,如果您想水平扩展应用程序(通过使用多个实例),快速路由应该永远不要使用任何全局内存中数据。无法保证同一客户端始终连接到同一服务器实例,因此全局存储的数据可能可用于一个请求,但不适用于下一个请求。在这种情况下,您必须找到一种方法在所有实例之间共享全局数据,这就是 Redis 在您的情况下已经做的事情。
<小时/>tl;dr: 仅访问请求处理程序中的 session 数据,然后将其作为参数传递给需要处理它的任何函数。如果您想水平扩展服务器,请不要在服务器中保留全局内存状态。
关于node.js - Node typescript 全局服务从函数返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53828696/