Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 快速回调中的SetTimeout_Javascript_Express_Web Development Server - Fatal编程技术网

Javascript 快速回调中的SetTimeout

Javascript 快速回调中的SetTimeout,javascript,express,web-development-server,Javascript,Express,Web Development Server,我正在创建一个路由,其中名为“active”的数据属性被设置为true,但一小时后被设置为false。我想知道在express回调中调用settimeout函数是可能的还是不好的做法。例如, app.get("/test", (req, res) => { //Some code SetTimeout(func, 3600); }); 这对缩放不利吗?如果这条路线被多次击中,会不会非常昂贵?提前感谢。似乎您只需要设置一个计时器。这假设“小时”从第一个请求开始 let timer =

我正在创建一个路由,其中名为“active”的数据属性被设置为true,但一小时后被设置为false。我想知道在express回调中调用settimeout函数是可能的还是不好的做法。例如,

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

//Some code

SetTimeout(func, 3600);
});

这对缩放不利吗?如果这条路线被多次击中,会不会非常昂贵?提前感谢。

似乎您只需要设置一个计时器。这假设“小时”从第一个请求开始

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
  }
})
//初始化
让计时器={}
//请求
如果(!计时器[用户]){
计时器[用户]=新日期().getTime()/1000+3600
}
else if(计时器[用户]{

如果(timers[user]将这些值存储在数据库中,则不应在节点中为每个条目创建一个计时器来重置此值。特别是如果它是一个持续时间较长的计时器,则通常不会在节点进程的内存中保留持续时间超过几秒钟的会话类/相关数据

访问您的站点的频率越高,您在任何时间运行至少一个计时器的可能性就越大。一旦出现这种情况,您就无法在不松开计时器的情况下重新启动应用程序。或者,您需要等待所有计时器完成,并且不接受任何新的计时器

您不能切换到集群模式,因为如果一个用户调用该路由两次,它可能会在两个不同的进程中结束,这些进程中的每一个都不知道另一个进程设置的超时


因此,更好的办法是在数据库中添加一个时间戳,一个清理计时器负责所有条目。

将“活动”数据属性存储在哪里?@ChrisCousins its在mongo数据库中,我将更改传递给settimeout的函数中的值。有一个“活动”吗数据属性,还是基于每个用户?因此,如果100人点击此路线,他们是否都有活动数据属性,还是仍然只有一个?您最好设置一个“expiresAt”时间戳字段;该字段将被计算(当调用/test时,每个用户)在未来3600秒。那么你运行的任何代码如果需要知道“active”是否为false,都会将当前时间与expiresAt进行比较。@ChrisCousins是的,我想这就是我要做的,尽管它需要更多的代码,但它似乎更具成本效益。谢谢你的帮助!还应该感谢Canada lol。