我试图实现这样的事情:
/* We use the command pattern to encode actions in
a 'command' object. This allows us to keep an audit trail
and is required to support 'undo' in the client app. */
CommandQueue.insert(command);
/* Queuing a command should trigger its execution. We use
an observer for this. */
CommandQueue
.find({...})
.observe({
added: function(command) {
/* While executing the action encoded by 'command'
we usually want to insert objects into other collections. */
OtherCollection.insert(...)
}
});
不幸的是,在CommandQueue上执行事务时,meteor似乎保持了OtherCollection的先前状态.暂时对OtherCollection进行更改.一旦CommandQueue上的事务完成,将恢复OtherCollection的先前状态,并且我们的更改将消失.
任何想法为什么会这样?这是预期的行为还是错误?
最佳答案 这是预期的行为,虽然它有点微妙,但不能保证(只是一个实现细节).
当命令插入CommandQueue时,立即观察到的回调.因此,当CommandQueue.insert方法运行时,插入到OtherCollection会发生,作为同一个调用堆栈的一部分.这意味着OtherCollection插入被视为CommandQueue插入的本地“模拟”的一部分,并且不会发送到服务器.服务器运行CommandQueue插入并将结果发回,此时客户端丢弃模拟结果并应用从服务器发送的结果,使OtherCollection更改消失.
更好的方法是编写自定义方法.就像是:
Meteor.methods({
auditedCommand: function (command) {
CommandQueue.insert(command);
var whatever = someProcessing(command)
OtherCollection.insert(whatever);
}
});
然后:
Meteor.call('auditedCommand', command);
这将立即显示在客户端上(延迟补偿)并且更安全,因为客户端无法在不添加到OtherCollection的情况下插入CommandQueue.
编辑:这可能会改变.添加的回调不应该被认为是CommandQueue.insert的本地模拟的一部分.这就是它现在的运作方式.也就是说,自定义方法可能仍然是一种更好的方法,即使其他人将命令添加到命令队列,它也会更有效,并且更安全.