延迟状态检查
tl;dr - 当某个 Action 在指定的持续时间内没有发生时,有哪些好的设计模式可以使用react?
问题设置
我正在制作类似 Farmville 的应用程序。在此应用程序中,用户拥有他们照料的花园。每个花园都会跟踪一些变量——湿度、温度、酸碱度、硝酸盐等。该应用程序会指导您照料花园,为您创建任务。根据您提交的读数,它会通知您这些变量中的任何一个是否太低或太高。此外,如果您在指定的时间内没有读取变量,它会提醒您读取变量。
花园数据长这样
// 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 成为 react 性数据源,每隔几分钟左右更新一次,并将其包装在 Tracker.autorun
中。
这通常是通过某种作业队列来处理的吗?
如果使用作业队列实现,当将来提交新的读数将过期日期后移时,是更新现有作业还是删除旧作业并创建新作业更好?
最佳答案
有什么方法可以被动地做到这一点吗? 是
这通常是通过某种作业队列来处理的吗? 是
我最推荐的模式是定期检查某种作业队列中是否存在“过期”事件。
至于 react 性——它并不是在所有情况下都能正常工作。有比基于定时器的依赖失效更有效的结构。
下面的代码,你可以用来驱动一个基于 react 的定时器系统,甚至是一个支持收集的定时器系统。
如果您觉得这个答案不太准确,请发表评论,以便我改进。
// 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;
})();
关于javascript - Meteor 中的延迟状态检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28283963/