在redis中存储node.js setTimeout的返回值

我在Node.js中使用setTimeout ,它似乎行为不同于客户端setTimeout因为它返回一个对象,而不是一个数字。 我想存储在redis中,但由于redis只存储string,我需要将对象转换为string。 但是,使用JSON.stringify会引发循环引用错误。 如何将这个对象存储在redis中,如果我想能够从redis中获取并调用clearTimeout呢?

您无法将对象存储在Redis中。 setTimeout方法返回一个Handler(对象引用)。

一个想法是在内存中创build自己的关联数组,并将索引存储在Redis中。 例如:

 var nextTimerIndex = 0; var timerMap = {}; var timer = setTimeout(function(timerIndex) { console.log('Ding!'); // Free timer reference! delete timerMap[timerIndex]; }, 5 * 1000, nextTimerIndex); // Store index in Redis... // Then, store the timer object for later reference timerMap[nextTimerIndex++] = timer; // ... // To clear the timeout clearTimeout(timerMap[myTimerIndex]); 

当超时服务器不需要在服务器重启时持久化时,使用此代码

 var timeouts = {}; app.get('/', function (req, res) { var index = timeouts.length; timeouts[index] = setTimeout(console.log, 1000000, req.user.name); redis.set('timeout:' + req.user.name, index, function (err, reply) { res.end(); }); }); app.get('/clear', function (req, res) { redis.get('timeout:' + req.user.name, function (err, index) { clearTimeout(timeouts[index]); delete timeouts[index]; redis.delete('timeout:' + req.user.name); res.end(); }); }); 

如果您需要超时重新启动服务器,则可能需要为redis中的每个计时器存储_idleStart_idleTimeout值,并在服务器重新启动时加载它们

 app.get('/', function (req, res) { var timeout = setTimeout(console.log, 1000000, req.user.name); var time = timeout._idleStart.getTime() + timeout._idleTimeout; redis.set('timeout:' + req.user.name, time, function (err, reply) { res.end(); }); }); app.get('/clear', function (req, res) { redis.delete('timeout:' + req.user.name); res.end(); }); // Load timeouts on server start // *I know this is not the correct redis command* // *It's not accurate, only approx* redis.get('timeout:*', function (err, vals) { vals.forEach(function (val) { var time = val - new Date().getTime(); setTimeout(console.log, time, username) }); }); 

我试图做与OP一样的事情。 我的解决scheme是在断开连接处理程序的超时时间内对一个新的键进行条件检查来设置超时时间:

 redis.hset("userDisconnecting:" + userId, "disconnect", 1); setTimeout(function() { redis.hget("userDisconnecting:" + userId, "disconnect", function(err, result) { if (result.toString() === "1") { //do stuff, like notify other clients of the disconnect. } }); }, 10000); 

然后,当客户端再次连接时,我将该键设置为0 ,所以在真正断开连接时需要触发的东西不会发生:

 redis.hset("userDisconnecting:" + userId, "disconnect", 0); 

超时本身在服务器重启时并不是永久的,但是你可以通过在启动时启动一个清理方法来解决这个问题。 连接的客户端会很快回到“在线”状态。