流星中的状态检查延迟
Delayed state checking in Meteor
延迟状态检查
tl;dr - 当操作在指定的持续时间内未发生时,有哪些好的反应设计模式?
问题设置
我正在制作一个类似Farmville的应用程序。在此应用程序中,用户拥有他们照顾的花园。每个花园都有几个变量被跟踪 - 湿度,温度,pH值,硝酸盐等。该应用程序将指导您照顾花园,为您创建任务。它会根据您提交的读数通知您这些变量中的任何一个是太低还是太高。此外,如果您在指定的时间内没有读取变量,它会提醒您读取变量。
花园数据看起来像
// garden object
{
name: "Home garden",
variables: {
nitrate: {
currentValue: 1.7,
lastMeasuredAt: // some Date
},
nitrite: {
currentValue: 0.5,
lastMeasuredAt: // some Date
}
}
}
因此,假设有一个名为"添加肥料"的任务。此任务的触发因素是硝酸盐低于 2.5ppm 的情况。假设任务数据看起来像
// task object
{
name: "Add fertilizer",
instructions: "Open bag, dump on garden",
condition: {
variable: "nitrate",
operator: "$lt",
threshold: 2.5
}
}
我使用condition
数据构建一个搜索查询,并查询花园以查看是否有任何符合该条件的内容。我使用的是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
}
}
我看到这是一个时间任务,因为它有一个interval
而不是一个threshold
并进行查询......
// 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
}
});
但这需要在将来的某个时候进行检查,而不是现在。这就引出了我问题的症结所在。检查何时过期的好方法是什么?
问题
有没有办法被动地做到这一点?
Meteor 的Tracker
仅支持在客户端上运行,但peerlibrary:server-autorun
确实在服务器上启用了它。我可以将 Date 设置为反应式数据源,每隔几分钟或其他时间更新一次,并将其包装在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;
})();
- 为什么不't Javascript对我的输入值进行了一些重新检查
- 在单击任何位置时隐藏元素,而不检查每次DOM单击
- 如何检查管道中未定义的项目
- 可以简化嵌套的延迟Q Promises解析吗
- 主干-不管怎样,检查事件以前是否绑定过
- 使用javascript检查多个输入值,并在1次检查中标记多个输入框
- 递归使用 eval() 是检查程序执行的好方法吗?
- 检查onsubmit doenst work jquery contactform上的函数
- JavaScript 检查隐藏字段中的值并将其设置为隐藏字段值
- API密钥使用和检查示例
- 如何让程序检查所选单词中是否有按键
- JS:检查URL中的参数,然后迭代一个参数为var的函数
- 用于检查数组中是否存在元素的javascript自定义方法
- 如何利用多链接延迟检查并显示ping结果,然后使用JavaScript选择最快的URL
- knockoutjs,复选框是有延迟的检查
- 如何在使用高阶组件进行身份验证时延迟检查redux存储
- 具有延迟的多个复选框选择以检查其他复选框更改
- 流星中的状态检查延迟
- 引用错误,用于使用 let 检查延迟声明的变量
- 如何使用 jquery 延迟对象检查元素是否在 DOM 中