为什么meteor撤消对嵌套在观察者方法中的集合的更改?

我试图实现这样的事情:

/* 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的本地模拟的一部分.这就是它现在的运作方式.也就是说,自定义方法可能仍然是一种更好的方法,即使其他人将命令添加到命令队列,它也会更有效,并且更安全.

点赞