【问题标题】:clear session specific timeout清除会话特定超时
【发布时间】:2019-11-27 21:40:14
【问题描述】:

我有一个快速应用程序,我在其中设置请求超时,并在满足条件时清除另一条路由请求的超时。问题是我无法在会话中存储超时(这是正常的,因为它是一个函数,而不是你可以 JSON.stringify() 的东西)。

我尝试创建一个全局变量:让超时并将超时分配给变量,但这不会正常工作,因为我有多个用户。因此,每次另一个用户发送请求时,都会重新分配超时变量。

我想做的一个小例子:

const route1 = (req, res) => {
    const timeout = setTimeout(() => {
        // do something
    }, 1000);

    req.session.timeout = timeout; // I know this does not work, but it is an example of what I would like to do
};

const route2 = (req, res) => {

    // if condition is met clear the above timeout for this user/session
    clearTimeout(req.session.timeout); // I know this does not work, but it is an example of what I would like to do
};

我可以将每个超时都存储在一个对象中,并将 sessionId 作为键,但我不确定这是必要的和/或执行此类操作的正确方法。

【问题讨论】:

  • 为什么不能使用会话?另外,超时应该是按用户还是全局应用?即一个用户可以启动计时器而另一个用户取消吗?
  • 因为你不能在会话中存储对函数的引用(我不知道)。超时只是我有充分理由做的事情,用户无法控制。
  • 是的,但它是一个整数值,它不是对函数本身的引用。我不明白为什么将值序列化到会话中会遇到问题。
  • 我刚刚检查了节点中 setTimeout 的行为,你是对的 - 它的工作方式与浏览器中的不同。事实上,it worked 正如我们在 node.js 的早期版本中所描述的那样。目前,它返回一个表示计划计时器而不是其 ID 的对象。您可以创建一个全局数组来保存类似{userId, setTimeoutResult} 的内容,而不是序列化setTimeout 结果并将其存储在会话中。然后你可以访问route2中的数组,找到给定的用户并清除存储的超时时间。
  • @Laurent 是的,抱歉,我错了。我应该先检查一下文档,有时候假设这些东西太容易了,因为它们的工作原理非常相似。

标签: javascript node.js express express-session


【解决方案1】:

这就是我实现这一目标的方式:

我用一个空对象创建一个新的 JS 文件:

let mapper = {

};

module.exports = mapper;

我是这样用的:

const route1 = (req, res) => {
    const {id: sessionId} = req.session;

    const timeout = setTimeout(() => {
        // do something
    }, 1000);

    mapper[sessionId] = timeout; // I put the timeout instance in the object with as key the sessionId
};

const route2 = (req, res) => {
    const {id: sessionId} = req.session;
    // if condition is met clear the above timeout for this user/session
    clearTimeout(mapper[sessionId]); // I get the Timeout instance from the object
};

那么问题是如果人们注销或会话被破坏/删除,我该如何清理这个文件。

我在 app.js 文件中导出了我的商店:

exports.app = app;
exports.store = store;

这就是我在 server.js 文件中清理映射器对象的方式:

const mapper = require('./mapperFile');
const store = require('./app').store;

setInterval(() => {
    const ids = Object.keys(mapper);

    for (let i = 0; i<  ids.length; i++) { // I loop through all the sessionIds (the keys of the Object)
        store.get(ids[i], (err, store) => { // I get the store for this key
            if (err) {
                // console.log(err);
            }
            else {
                if (!store) {
                    delete mapper[ids[i]]; // If the session is removed I delete this from the object
                }
            }
        });
    }
}, 2000); // I don't know if 2 seconds is a good time but you get the idea

我希望这对其他人有所帮助。我仍然不知道这是否是正确的方法,但它对我有用。

【讨论】:

  • 使用这种方法的唯一问题是可扩展性,它不适用于多进程架构。
  • 嗨@James,我不确定这里是否适合做这件事,但你能否告诉我更多关于多进程架构的信息。我认为节点是单线程的。我不擅长这些话题,但想了解更多,我感觉你知道很多。有没有办法可以在堆栈上与您联系?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-09
  • 2012-02-08
  • 2019-05-21
  • 1970-01-01
  • 2014-06-21
  • 2013-01-09
  • 1970-01-01
相关资源
最近更新 更多