14

私はNode.jsで使用していますが、数値ではなくオブジェクトを返すという点でsetTimeout、クライアント側とは動作が異なるようです。setTimeoutこれをredisに保存したいのですが、redisは文字列しか保存しないので、オブジェクトを文字列に変換する必要があります。ただし、を使用JSON.stringifyすると循環参照エラーがスローされます。このオブジェクトをredisからフェッチして呼び出すことができるようにするには、どうすればこのオブジェクトをredisに保存できclearTimeoutますか?

4

4 に答える 4

2

オブジェクトを Redis に保存することはできません。このsetTimeoutメソッドは Handler (オブジェクト参照) を返します。

1 つのアイデアは、メモリ内に独自の連想配列を作成し、インデックスを 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]);
于 2012-07-02T21:35:10.393 に答える
1

OPと同じことをしようとしていました。私の解決策は、切断ハンドラーのタイムアウト内の新しいキーの条件付きチェックでタイムアウトを設定することでした:

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

タイムアウト自体はサーバーの再起動後も永続的ではありませんが、起動時にスイーパー メソッドを開始することで解決できます。接続されたクライアントは、すぐに「オンライン」に戻ります。

于 2014-04-10T22:43:06.230 に答える
0

このコードは、サーバーの再起動後もタイムアウトを持続させる必要がない場合に使用されます

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)
  });
});
于 2012-07-02T21:57:55.967 に答える