在express回调中使用SetTimeout

3
我正在创建一个路由,其中一个名为“active”的数据属性被设置为true,但在一小时后会被设置为false。我想知道在Express回调函数中调用settimeout函数是否可行或者是否不好的做法。例如:
app.get("/test", (req, res) => {

//Some code

SetTimeout(func, 3600);
});

如果这个路由被频繁访问,会对扩展性产生不利影响吗?感谢您的提前回复。


"active" 数据属性存储在哪里? - Chris Cousins
@ChrisCousins,它在Mongo数据库中,我将更改传递给setTimeout的函数中的值。 - Kai Ferrall
有一个“活动”的数据属性,还是每个用户都有一个?所以如果有100个人访问这个路由,他们是否都有一个活动的数据属性,还是仍然只有一个? - Chris Cousins
@ChrisCousins 是的,这将是基于每个用户的。所以我担心如果有很多人访问该路由会受到影响。 - Kai Ferrall
1
最好设置一个“expiresAt”时间戳字段;该字段将在每个用户调用“/test”时计算为未来3600秒。然后,任何需要知道“active”是否为false的代码实际上都会将当前时间与expiresAt进行比较。 - Chris Cousins
1
@ChrisCousins 是的,我想这就是我要做的,尽管需要更多的代码,但它似乎更具成本效益。感谢您的帮助!还要向加拿大喊话哈哈。 - Kai Ferrall
2个回答

1
如果您将这些值存储在数据库中,那么您不应该为每个条目在节点中创建一个会重置此值的计时器。特别是如果它是持久性计时器,则应该将持续时间超过几秒钟的Session等/相关数据通常不保留在节点进程的内存中。
您的网站被访问得越频繁,就越有可能在任何时候都会有至少一个计时器正在运行。一旦出现这种情况,您将无法重新启动应用程序,而不是失去该计时器。或者您需要等待所有计时器完成,同时不接受任何新的计时器。
而且您不能切换到集群模式,因为如果一个用户调用该路由两次,它可能会结束在两个不同的进程中,每个进程都不知道其他进程设置的超时时间。
因此,更好的想法是向数据库中添加一个时间戳,并添加一个负责所有条目的清理计时器。

0

看起来你只需要设置一个计时器。这假定“小时”从第一次请求开始。

let timer = null
let data = true

app.get("/test", (req, res) => {

  //Some code
  if (!timer) {
    timer = setTimeout(() => {data=false}, 3600);
  }
});

相反地,对于多个用户,您可以通过在哈希中放置时间戳并按请求或单独的间隔计时器轮询它来避免设置多个计时器。

// init
let timers = {}

// in request
if (!timers[user]) {
    timers[user] = new Date().getTime() / 1000 + 3600
}
else if (timers[user] <= new Date().getTime() / 1000)
{
    // update db, etc
}


// or poll for expirations in separate single timer routine
let now = new Date().getTime() / 1000
Object.keys(timers).forEach(user => {
  if (timers[user] <= now) {
    // update db, etc
  }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接