节点打字稿全局服务,以从函数返回值

时间:2018-12-18 08:06:56

标签: node.js typescript global

我正在尝试为我的后端实现一个服务,该服务允许从代码中的任何位置调用会话数据,这意味着我想创建一个服务文件,该文件从获取会话数据的函数中导出值。否则,我只能从同时具有req:Request和res:Response参数的函数中获取会话数据。因此,我基本上是试图将值锁定到一个变量,该变量可以在项目的任何地方使用和调用。我的代码现在看起来像这样,但是如果我在文件中的其他任何地方使用导出,它只会打印实际的代码(函数)代码段,而不是代码内部指定的返回值。一般来说,我对打字稿和节点还很陌生,这意味着我可能在这里犯了一些非常愚蠢的错误。

感谢您提前提供的所有帮助! /维克多

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参数的情况下访问数据(如果可能)。

2 个答案:

答案 0 :(得分:2)

首先,对会话进行简短说明:

  • 用户登录(并验证其凭据,etz)后,将为该用户启动新会话。
  • 您正在使用的中间件将为此会话分配一个唯一的ID,您可以为其分配一些数据。
    • ID 以cookie的形式传输到用户浏览器
    • 数据存储在服务器上(根据您的情况,为Redis)
  • 中间件将检查请求中是否包含具有有效ID的会话cookie,并执行以下操作:
      从Redis
    • 获取给定 ID 的Session- 数据
    • 使用来自Redis的 Data 填充req.session对象
    • 呼叫下一条路线

不建议这样做:不要将会话数据存储在应用程序内存中。为什么?数据应仅在用户请求的上下文中相关。您需要会话数据来处理请求,否则就不需要它。

不是将其全局存储,而是构建处理程序和函数以接受特定的Session- Data 作为参数,例如:

// 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);
    }
}

这有两个重要的优点:

  1. 您不必将会话 Data 与Redis中的会话保持同步
  2. 这些(几乎)pure functions使您的代码更易于理解

如果编写的函数完全可以使用它们的输入参数,并且不使用任何全局状态,则“调用函数的顺序”或“检查数据是否可用”之类的内容就变得无关紧要。呼叫者负责获取数据,被呼叫者负责处理数据。

此外,如果您想水平扩展应用程序(使用多个实例),则快速路由应该不要使用任何全局内存数据。无法保证同一客户端将始终连接到同一服务器实例,因此全局存储的数据可能可用于一个请求,但不能用于下一个请求。在这种情况下,您将必须找到一种在所有实例之间共享全局数据的方法,这是Redis在您的案例中已经做过的事情。


tl; dr::仅在请求处理程序中访问会话数据,然后将其作为参数传递给需要处理的任何函数。如果您想水平扩展它,请不要在服务器中保留全局内存状态。

答案 1 :(得分:0)

您可以将数据写入madvic或db或文件中,但是我们也可以使用全局变量。但是,据我所知,全局变量是一种不好的做法,因此最好将数据写入某人。