2013-01-10 26 views
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(...) 
     } 
    }); 

遺憾的是,似乎流星保持OtherCollection的以前的狀態,而在CommandQueue執行交易。對OtherCollection進行臨時更改。一旦CommandQueue的交易完成,OtherCollection的先前狀態將會恢復,但我們的更改消失。

任何想法爲什麼會發生這種情況?這是預期的行爲還是錯誤?

回答

2

這是預期的行爲,儘管它有點微妙,並沒有保證(只是一個實現細節)。

當命令插入到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); 

這將立即顯示在客戶端(延遲補償),是更安全,因爲客戶不能插入到CommandQueue不也增加OtherCollection

編輯:這可能會改變。添加的回調不應該真的被認爲是CommandQueue.insert的本地模擬的一部分。這就是現在它的工作方式。也就是說,自定義方法可能仍然是一個更好的方法,即使其他人將命令添加到命令隊列並且更安全,它也可以工作。

+0

偉大的答案:-) – jerico

+0

只要我在我的項目中有'不安全'的包,這種解決方案工作正常。刪除它會在客戶端的OtherCollection.insert()中引發'插入失敗:拒絕訪問'。我顯然需要模擬來獲得良好的響應時間。但是我不能讓客戶寫入對OtherCollection的訪問權限,因爲必須通過經審計的事務來改變路由。任何想法如何在這種情況下暫時模擬這種變化直到從服務器返回「真正」的變化? – jerico

0

我不知道你的觀察行爲,但我們使用服務器端allow方法完成同樣的事情:

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

這也是不是把這個邏輯客戶端更安全。

+0

感謝您的回答!我在做這個客戶端,因爲它直接影響用戶在屏幕上看到的內容。所以我想避免連接的延遲(這是流星的一大優點,對吧)?我正在使用不安全的軟件包,所以安全性不應該是一個問題... – jerico

+0

...我承認在概念上我不相信allow()方法是做數據更新的正確位置。這似乎是一個黑客... – jerico

相關問題