2016-04-16 18 views
1

Gibt es eine Möglichkeit, Meteor.call oder Meteor.apply mitzuteilen, nur den clientseitigen Stub auszuführen und die Servermethode nicht aufzurufen?Rufen Sie die Meteor-Methode nur auf dem Client auf

Nehmen wir an, wir haben die Todo-Liste Beispiel. Vielleicht wollen wir anonym (nicht angemeldet) Benutzer einige Standardaufgaben zeigen:

  • versuchen, eine Aufgabe zu überprüfen
  • Umbenennen einer
  • Fügen Sie Ihre eigenen
  • Konto erstellen

Benutzer, die angemeldet sind, sollten ihre Aufgaben sehen, und wir möchten nicht alle Funktionen zweimal implementieren (einmal für registrierte und einmal für anon) ymous Benutzer).

Wenn dies auf die normale Art und Weise implementiert wird, überträgt Meteor die Änderungen an alle verbundenen Clients, was bedeutet, dass alle anonymen Benutzer die gleichen Aufgaben teilen und die Änderungen anderer in Echtzeit sehen.

Das Hinzufügen eigener Aufgaben für jeden anonymen Benutzer würde die Datenbank mit nutzlosen Dingen füllen.

So suche ich nach einer Möglichkeit, nur die Methoden auf der Clientseite if (!Meteor.user()) ausführen.

+1

Warum es so kompliziert machen, warum nicht einfach die gewünschte Funktion erstellen und direkt anrufen? Sie können immer noch dieselbe Funktion innerhalb des Methoden-Stubs für Konsistenz verwenden. –

+0

Was meinst du? Die Schnittstelle rendert die Aufgaben-Sammlung. Die Tasks-Sammlung wird auf dem Server aktualisiert und an den Client weitergeleitet. Was meinst du mit "Erstelle die Funktion [...] und rufe sie direkt an"? Welche Funktion würde ich erstellen? Wie man es direkt nennt? – Dominik

Antwort

0

Es gibt verschiedene Ansätze dazu:

Gerade diese todos in der Datenbank (sowieso) hinzuzufügen.

Dies ist die einfachste Methode, da Sie Ihrer App keine zusätzliche Logik hinzufügen (mit Ausnahme des Hinzufügens von Daten zu Ihrer App, wenn sich ein anonymer Benutzer an Ihrer App anmeldet).

Sie sagten, es würde "die Datenbank mit nutzlosen Dingen füllen", aber ist es wirklich wichtig? Die kompletten Werke von Shakespeare wiegen etwa 5MB, wahrscheinlich hast du damit kein Problem.

Wenn Sie diesen Weg gehen, möchten Sie möglicherweise ein anonymen Account-System hinzufügen, um zu referenzieren, welcher Benutzer welche Elemente besitzt. Ich würde das artwells:accounts-guest Paket empfehlen, aber es gibt einige andere.

Verwenden Sie eine Client-only-Sammlung.

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

Sie wollen diesen Code, um sicherzustellen, nur auf der Client-Seite lief, also entweder:

  • umgeben es mit if(Meteor.isClient);
  • oder legen Sie es in eine Datei in der /your-root-project/client Ordner.

Aber dann müssen Sie mehr Logik in allen Orten hinzufügen, wo Sie mit todos beschäftigen:

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 
      } 

     }, 
    }); 

Sie können sehen, dass es durchaus mehr Logik, man könnte es in einer Funktion einpacken, wie :

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" 
    } 

Aber Sie sehen, es gibt andere Probleme (Sie wissen nicht, wo die todo herkommt, haben Sie keine Kontrolle auf der Server-Seite haben, ...). Sie könnten auch die todos Flagge (fügen Sie ein „isDummy“ Feld, wie:

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

Aber auch hier, dann können Sie an dieser Flagge überall sehen müssen werde Es ist nicht zukunftssicher

Verwendung Ebene. JavaScript-Objekte und Funktionen

ich denke, das ist das, was @ christian-fritz in den Kommentaren zu Ihrer Frage vorgeschlagen Sie schlicht JavaScript-Objekte nutzen könnten, und kombiniere sie mit Ihnen Sammlung.

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

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

Aber dann würden Sie verlieren die Reaktivität der Sammlung:

In Ihrem Meteor Methode, um die todo Objekt direkt, ob es eine _id Feld, und aktualisieren Sie es dementsprechend wie folgt aus (vereinfacht) senden Sie könnten und die Vorlage (die Sie selbst implementieren können, mit Tracker Dependency, aber auch dies ist nicht der einfachste Weg).

TL; DR: Diese Beispiele zeigen, warum es eine schlechte Idee ist, zwei verschiedene Datenspeicher für ein ähnliches Objekt zu haben, besonders wenn sie unterschiedliche APIs haben, und Sie können keinen "Mock" der Sammlung erstellen wäre dem Mongo-Sammlungsobjekt ähnlich. Wenn die "Todos" kein wichtiges Objekt in Ihrer App wären, könnten Sie eine Alternative verwenden, wie die, die ich gezeigt habe, aber hier wird wahrscheinlich 10% mehr Code in Ihrer ganzen App, wenn nicht mehr. Also benutze die serverseitige Sammlung.

Verwandte Themen