2016-04-16 64 views
1

有沒有什麼辦法可以告訴Meteor.callMeteor.apply只運行客戶端存根而不調用服務器方法?僅在客戶端調用流星方法

假設我們有待辦事項列表示例。也許我們要顯示匿名(未登錄)用戶的一些默認任務:

  • 嘗試查看任務
  • 重命名一個
  • 添加您自己
  • 創建帳戶

登錄的用戶應該看到他們的任務,我們不希望實現所有功能兩次(一次用於註冊,一次用於匿名ymous用戶)。

如果這是以正常方式實施,Meteor會將更改推送給所有連接的客戶端,這意味着所有匿名用戶將共享相同的任務並實時查看他人的編輯。

爲每個匿名用戶添加自己的任務將填充無用的東西的數據庫。

所以我正在尋找一種方法來只運行在客戶端if (!Meteor.user())方法。

+1

爲什麼這麼複雜,爲什麼不直接創建你想要的函數並直接調用它呢?您仍然可以在方法存根中使用相同的函數來保持一致性。 –

+0

你是什麼意思?界面呈現任務集合。 Tasks集合在服務器上更新並推送到客戶端。 「創建函數並直接調用」意味着什麼?我會創建哪個功能?如何直接調用它? – Dominik

回答

0

有不同的方法,以這樣的:

數據庫(反正)只需添加的待辦事項。

這是最簡單的方法,因爲您不會嚮應用程序添加任何其他邏輯(除非將匿名登錄到應用程序時嚮應用程序添加數據)。

你說它會「用無用的東西填充數據庫」,但它真的很重要嗎?莎士比亞的全部作品重量約爲5MB,你可能不會有任何問題。

如果你這樣做,你可能想要添加一個匿名帳戶系統,以引用哪個用戶擁有哪些項目。我會推薦artwells:accounts-guest包,但還有一些其他的。

使用客戶端專用集合。

DummyTodos = new Mongo.Collection('dummy-todos'); 

你要確保這個代碼僅運行在客戶端,所以無論是:

  • if(Meteor.isClient)圍繞着它;
  • 或將其放在/your-root-project/client文件夾中的文件中。

但隨後你將不得不在所有地方添加更多的邏輯,你處理待辦事項:

Meteor.methods({ 
     'todo.setChecked'(todoId, isChecked) { 
     check(todoId, String); 
     check(isChecked, Boolean); 
      var todo = Todos.findOne(todoId); 
      var todoClass = Todos; 

      if(!todo && Meteor.isClient){ 
       todo = DummyTodos.findOne(todoId); 
       todoClass = DummyTodos 
      } 

      if(todo) { 
       todoClass.update(todoId, { $set: { checked: isChecked } }); 
      } else if(Meteor.isClient){ 
       // On the server side, you don't know whether something went wrong, or it was just a local todo 
       // So you're losing some error handling here, which isn't good 

       // You can still deal with this on the client-side, maybe you want to: 
       throw "No todo with id " + todoId; 
       // or just 
       return; 
       // But the server will fail silently, so you're losing error handling 
      } 

     }, 
    }); 

你可以看到,有相當多的邏輯,你可以在一個功能包起來,像:

var getTodoOrDummyTodo: function(todoId) { 
     var todo = Todos.findOne(todoId); 

     if(!todo && Meteor.isClient){ 
      todo = DummyTodos.findOne(todoId); 
     } 

     // I return some todo, but I don't know where it comes from 
     if(todo) 
      return todo; 
     else 
      throw "Well, something wrong happened but I'm not sure what" 
    } 

但你看到有其他問題(你不知道那裏的待辦事項來自於,你對服務器端沒有控制,...)。你也可以舉報該待辦事項(增加一個「isDummy」領域,如:

Meteor.methods({ 
     'todo.setChecked'(todoId, isChecked) { 

但同樣,這意味着你必須看看這個標誌隨處可見它不是面向未來

使用平原。 JavaScript對象和功能

我想這是@基督教弗裏茨在評論你的問題建議你可以使用普通的JavaScript對象,並與你的收集將它們合併:

var dummyTodos = [ 
     {text: "Hello", checked: true}, 
     {text: "Bye", checked: false} 
    ] 

    var todos = Todos.find(); 
    if(todos.count() < 1){ 
     return dummyTodos; 
    } else { 
     return todos; 
    } 

在您的流星方法,你可以直接發送ToDo對象,檢查是否有一個_id領域,並相應地更新它,像這樣(簡化):

不過,你就失去了收藏的反應和模板(你可以使用Tracker Dependency來實現自己,但這又不是最簡單的方法)。

TL; DR:這些例子說明了爲相似的對象使用兩個不同的數據存儲是個壞主意,特別是如果它們具有不同的API,並且不能創建集合的「模擬」將類似於mongo集合對象。如果「todos」不是您應用中的重要對象,那麼您可以使用替代方法,就像我之前展示的方法一樣,但這樣可能會使整個應用中的代碼增加10%,甚至更多。所以使用服務器端收集。