3

ユーザーがクライアントからアラームを設定してサーバーに渡すことを許可しようとしています。次に、サーバーにはカウントダウンする setTimeout があり、時間がなくなると関数が実行されます。

この最初の部分は正常に動作していますが、クライアントが特定のアラームをキャンセルすることを決定した場合に、同じタイムアウトをクリアする機能が必要です。

注: Redis を使用してさまざまなデータを保存してきたので、それが利用可能です。

var client = redis.createClient();
io.set("store", new sio.RedisStore);

io.sockets.on('connection', function (socket) {

socket.on('alarm:config', function(list, date, time, bool) {

  if (bool) {

    var now = new Date().getTime();

    var year = date[0],
        month = date[1] - 1,
        day = date[2];

    var hour = time[0],
        minutes = time[1];

    var alarm = new Date(year, month, day, hour, minutes);

    var countdown = alarm - now;

    var myAlarm = setTimeout(function() {

      // do stuff...

    }, ( countdown ) );

  } else {

    clearTimeout(myAlarm);

  }

});
});

私が念頭に置いているアプローチは、ブール値を使用して、ユーザーがその特定のアラームを設定しているかキャンセルしているかを判断することです。ローカル変数「myAlarm」を設定してもうまくいかないことに気づきました。アイデアを伝えるためにそこに置いただけです。

その正確なタイムアウトへの参照を保存する方法を見つけようとしています。これにより、次回「alarm:config」ソケット イベントが偽のブール値でトリガーされたときに、以前に設定されたタイムアウトをキャンセルできるようになります。

それはまったく別の質問かもしれませんが、Google カレンダーのようなアプリケーションはどのようにして日付と時刻を保存し、それをトリガーするタイミングを正確に把握し、キャンセルする機能を提供するのでしょうか? これは本質的に同じ考えです。

更新:次のソリューションを使用して動作しています。私はよりエレガントなソリューションを受け入れています。

socket.on('alarm:config', function(list, date, time, bool) {

  var alarmName = "timer:" + list;

  if (bool) {

    client.hset(alarmName, "status", true);

    var now = new Date().getTime();

    var year = date[0],
        month = date[1] - 1,
        day = date[2];

    var hour = time[0],
        minutes = time[1];

    var alarm = new Date(year, month, day, hour, minutes);

    var countdown = alarm - now;

    setTimeout(function() {

      client.hget(alarmName, "status", function(err, bool) {

        if(bool == 'true') {

          // do stuff...

        } else {

          console.log("This alarm has been canceled.");

        }

      });

    }, ( countdown ) );

  } else {

    console.log('canceling alarm');
    client.hset(alarmName, "status", false);

  }
});
4

1 に答える 1

1

構築するアプリケーションの大きさに応じて、いくつかのオプションがあります。

処理キュー

単にタイマーを設定する代わりに、ジョブキューを使用するようにアプリケーションを再構築することができます。これには、将来的に複数のプロセスに分割できるという利点がありますが、処理が少し複雑になります。

KueのようなライブラリはRedisだけを使用しており、将来のイベントを設定するために遅延プットを実行できます。

Kueのreadmeからの説明:

var kue = require('kue')
  , jobs = kue.createQueue();

// Create delayed job (need to store email.id in redis as well)
var email = jobs.create('email', {
    title: 'Account renewal required',
    to: 'tj@learnboost.com',
    template: 'renewal-email'
}).delay(minute).save();

// Process job
jobs.process('email', function(job, done){
  email(job.data.to, done);
});

// Cancel job
email.remove(function(err){
  if (err) throw err;
  console.log('removed completed job #%d', job.id);
});

タイムアウトへの参照の保存

これははるかに堅牢ではありませんが、非常に簡単に実行できる可能性があります。グローバル変数が浮かんでいるままになり、プロセスがクラッシュしても回復しません。

基本的に、タイマーをグローバル変数に格納し、ジョブIDに基づいてキャンセルします。

var myAlarms = {}

socket.on('alarm:config', function(list, date, time, bool) {
  var alarmName = "timer:" + list;

  if (bool) {

    myAlarms[alarmName] = setTimeout(function() {
      // do stuff...
    }, countdown);

  } else {
    clearTimeout(myAlarms[alarmName]);
  }
}

注:このコードはいずれもテストされておらず、エラーが含まれている可能性があります。

于 2013-02-27T22:45:19.250 に答える