4

我正在尝试实现这样的事情:

/* 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(...)
       }
   });

不幸的是,meteor 似乎保持了在OtherCollection执行交易时的先前状态CommandQueue。对OtherCollection. 但是,一旦事务完成,就会恢复CommandQueue先前的状态,并且我们的更改就会消失。OtherCollection

任何想法为什么会发生这种情况?这是预期的行为还是错误?

4

2 回答 2

2

这是预期的行为,尽管它有点微妙,并且不能保证(只是一个实现细节)。

当命令插入时,观察的回调立即触发CommandQueue。因此,插入OtherCollection发生在CommandQueue.insert方法运行时,作为同一调用堆栈的一部分。这意味着OtherCollection插入被认为是插入的本地“模拟”的一部分CommandQueue,并且不会发送到服务器。服务器运行CommandQueue插入并将结果发回,此时客户端丢弃模拟结果并应用从服务器发送的结果,使OtherCollection更改消失。

更好的方法是编写自定义方法。就像是:

Meteor.methods({
  auditedCommand: function (command) {
    CommandQueue.insert(command);

    var whatever = someProcessing(command)
    OtherCollection.insert(whatever);
  }
});

然后:

Meteor.call('auditedCommand', command);

这将立即显示在客户端上(延迟补偿),并且更安全,因为客户端无法插入到CommandQueue而不添加到OtherCollection.

编辑:这可能会改变。添加的回调不应真正被视为 CommandQueue.insert 的本地模拟的一部分。这就是它现在的工作方式。也就是说,自定义方法可能仍然是更好的方法,即使其他人将命令添加到命令队列,它也可以工作,并且更安全。

于 2013-01-11T23:03:26.987 回答
0

我不确定您的观察行为,但我们使用服务器端允许方法完成了同样的事情:

CommandQueue.allow ({
  insert: function (userId, doc) {
    OtherCollection.insert(...);
    return (userId && doc.owner === userId);
  }
});

这也比把这个逻辑放在客户端更安全。

于 2013-01-11T04:08:32.497 回答