Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.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 Meteor中的延迟状态检查 延迟状态检查_Javascript_Mongodb_Design Patterns_Meteor - Fatal编程技术网

Javascript Meteor中的延迟状态检查 延迟状态检查

Javascript Meteor中的延迟状态检查 延迟状态检查,javascript,mongodb,design-patterns,meteor,Javascript,Mongodb,Design Patterns,Meteor,tl;dr-当一个动作在指定的时间内没有发生时,有哪些好的设计模式可以做出反应 问题设置 我正在做一个类似Farmville的申请。在这个应用程序中,用户拥有他们负责的花园。每个花园都有一些可跟踪的变量——湿度、温度、ph值、硝酸盐等。该应用程序指导您管理花园,为您创建任务。根据您提交的读数,它会通知您这些变量是否过低或过高。此外,如果在指定的时间内没有读取变量,它会提醒您读取变量的读数 花园数据看起来像 // garden object { name: "Home garden",

tl;dr-当一个动作在指定的时间内没有发生时,有哪些好的设计模式可以做出反应


问题设置 我正在做一个类似Farmville的申请。在这个应用程序中,用户拥有他们负责的花园。每个花园都有一些可跟踪的变量——湿度、温度、ph值、硝酸盐等。该应用程序指导您管理花园,为您创建任务。根据您提交的读数,它会通知您这些变量是否过低或过高。此外,如果在指定的时间内没有读取变量,它会提醒您读取变量的读数

花园数据看起来像

// garden object
{
  name: "Home garden",
  variables: {
    nitrate: {
      currentValue: 1.7,
      lastMeasuredAt: // some Date
    },
    nitrite: {
      currentValue: 0.5,
      lastMeasuredAt: // some Date
    }
  }
}
// task object
{
  name: "Add fertilizer",
  instructions: "Open bag, dump on garden",
  condition: {
    variable: "nitrate",
    operator: "$lt",
    threshold: 2.5
  }
}
所以让我们假设有一个任务叫做“添加肥料”。此任务的触发条件是硝酸盐低于2.5ppm。假设任务数据如下所示

// garden object
{
  name: "Home garden",
  variables: {
    nitrate: {
      currentValue: 1.7,
      lastMeasuredAt: // some Date
    },
    nitrite: {
      currentValue: 0.5,
      lastMeasuredAt: // some Date
    }
  }
}
// task object
{
  name: "Add fertilizer",
  instructions: "Open bag, dump on garden",
  condition: {
    variable: "nitrate",
    operator: "$lt",
    threshold: 2.5
  }
}
我用
条件
数据构建了一个搜索查询,并查询花园以查看是否有与该条件匹配的花园。我使用的是MongoDB,所以可以使用普通的老Javascript对象和Meteor形成查询,所以我有一个实时更新游标

query = { variables.nitrate.currentValue: { $lt : 2.5 }};
Gardens.find(query).observe({
  added: function( garden ) {
    // add the task to the garden's task list
  },
  removed: function( garden ) {
    // remove the task from the garden's task list
  }
});
问题 好消息是,这种模式适用于我描述的任务。但是,如果任务是基于一段时间后的持续时间,该怎么办

// time-based task object
{
  name: "Take a nitrate reading",
  instructions: "Insert the nitrate probe",
  condition: {
    variable: "nitrate",
    operator: "$lt",
    interval: 2880 // 2 days in minutes
  }
}
我看到这是一个时间任务,因为它有一个
间隔,而不是
阈值,并使查询

// using moment.js
expiration = moment().subtract(interval, 'minutes').toDate();
// find when lastMeasuredAt + interval < Now
query = { variables.nitrate.lastMeasuredAt: { $gt: expiration }};
Gardens.find(query).observe({
  added: function( garden ) {
    // add the task to the garden's task list
  },
  removed: function( garden ) {
    // remove the task from the garden's task list
  }
});
//使用moment.js
过期=时刻()。减去(间隔,'分钟')。toDate();
//查找上次测量的时间+间隔<现在
query={variables.notrite.lastmasuredat:{$gt:expiration};
花园。查找(查询)。观察({
新增:功能(花园){
//将任务添加到花园的任务列表中
},
移除:功能(花园){
//从花园的任务列表中删除该任务
}
});
但这需要在将来的某个时候进行检查,而不是现在。这就引出了我问题的关键。什么是检查过期时间的好方法

问题 有没有什么方法可以做出反应? Meteor的
跟踪器
仅支持在客户端上工作,但在服务器上确实启用了它。我可以将日期作为一个反应式数据源,每隔几分钟或其他时间更新一次,然后将其包装在
Tracker.autorun

这通常是通过某种作业队列来处理的吗?
如果使用作业队列实现,当将来提交新的读取并将过期日期推后时,是更新现有作业还是删除旧作业并创建新作业更好?

有没有反应性的方法?对

这通常是通过某种作业队列来处理的吗?对

我最推荐的模式是定期检查某种作业队列中的“过期”事件

至于反应性——它并不是在所有情况下都能很好地工作。有更有效的结构可以防止基于计时器的依赖项失效

下面的代码,您可以用来为基于无功的定时器系统供电,甚至是为基于采集的定时器系统供电

如果你觉得这个答案不太中肯,请发表评论,这样我可以改进它

// executes it's tasks regularly.
// up to the tasks system to implement "enqueue" & "execute"
ScheduledExecutor = (function() {

  function ScheduledExecutor(tasks, checkInterval) {
    this.tasks = tasks;
    this.checkInterval = checkInterval;
    this.running = false;
    this.timer = null;
    this.tick = _.bind(this.tick, this);
  }

  _.extend(ScheduledExecutor.prototype, {
    enqueue: function(task){
      this.tasks.enqueue(task);
    },
    tick: function(){
      this.tasks.execute();
      if (this.running) {
        this.timer = Meteor.setTimeout(this, this.checkInterval);
      }
    },
    start: function(){
      if (!this.running){
        this.running = true;
        this.tick();
      }
    },
    stop: function(){
      this.running = false;
      Meteor.clearTimeout(this.timer);
      this.timer = null;
    }
  });
  return ScheduledExecutor;
})();

// example of "reactive" task list.
//  finds due dependencies, and invalidates them
ReactiveTasks = (function(){
  function ReactiveTasks(){
    this.taskList = [];
  }

  _.extend(ReactiveTasks.prototype, {
    execute: function(){
      var now = Date.now();
      _.findWhere(this.taskList, function(task){
        return task.due <= now;
      }).forEach(function(task){
        task.dep.changed()
      });
      this.taskList = _.filter(this.taskList, function(task){
        return task.due > now;
      });
    },
    enqueue: function(due){
      var dep = new Tracker.Dependency;
      dep.depend();
      this.taskList.push({
        due: due,
        dep: dep
      });
    }
  });
  return ReactiveTasks;
})();

// executes tasks backed by a collection
//  finds "due" tasks, then calls the "executor"
//  the executor should interpret the task, and 
/// call the correct library function
CollectionTasks = (function(){
  function CollectionTasks(collection, executor){
    this.collection = collection;
    this.executor = executor;
  }
  _.extend(CollectionTasks.prototype, {
    execute: function(){
      var self = this, 
        now = Date.now();
      self.collection.find({
        due: {
          $lte: now
        }
      }).forEach(function(task){
        self.collection.remove({_id: task._id});
        self.executor.execute(task);
      });
    },
    enqueue: function(task){
      this.collection.insert(task);
    }
  });
  return CollectionTasks;
})();
//定期执行其任务。
//直至任务系统实现“排队”和“执行”
ScheduledExecutor=(函数(){
功能计划执行器(任务、检查间隔){
这个。任务=任务;
this.checkInterval=checkInterval;
this.running=false;
this.timer=null;
this.tick=u.bind(this.tick,this);
}
_.extend(ScheduledExecutor.prototype{
排队:函数(任务){
this.tasks.enqueue(任务);
},
勾选:函数(){
this.tasks.execute();
如果(这个正在运行){
this.timer=Meteor.setTimeout(this,this.checkInterval);
}
},
开始:函数(){
如果(!this.running){
这是真的;
这个。勾选();
}
},
停止:函数(){
this.running=false;
Meteor.clearTimeout(this.timer);
this.timer=null;
}
});
返回调度执行器;
})();
//“被动”任务列表示例。
//查找到期的依赖项,并使其无效
反应性任务=(函数(){
函数反应任务(){
this.taskList=[];
}
_.extend(ReactiveTasks.prototype{
执行:函数(){
var now=Date.now();
_.findWhere(此.taskList,函数(任务){
返回任务。现在到期;
});
},
排队:功能(到期){
var dep=新的Tracker.Dependency;
dep.dependen();
这个是.taskList.push({
到期:到期,,
副部长:副部长
});
}
});
返回反应性任务;
})();
//执行集合支持的任务
//查找“到期”任务,然后调用“执行者”
//执行人应解释任务,以及
///调用正确的库函数
CollectionTasks=(函数(){
函数集合任务(集合、执行器){
this.collection=collection;
this.executor=执行人;
}
_.extend(CollectionTasks.prototype{
执行:函数(){
var self=这个,
now=Date.now();
self.collection.find({
到期日:{
$lte:现在
}
}).forEach(功能(任务){
self.collection.remove({u-id:task.\u-id});
self.executor.execute(任务);
});
},
排队:函数(任务){
this.collection.insert(任务);
}
});
返回收集任务;
})();