2014-07-10 6 views
11

Sagen Sie, ich habe einen TodoStore. Der TodoStore ist verantwortlich für die Aufbewahrung meiner TODO-Artikel. Todo-Elemente werden in einer Datenbank gespeichert.Asynchrone Daten laden in Fluss speichert

Ich möchte wissen, was die empfohlene Methode zum Laden aller Todo-Elemente in den Laden ist und wie die Ansichten mit dem Laden interagieren sollten, um die TODO-Elemente beim Start zu laden.

Die erste Alternative besteht darin, eine loadTodos Aktion zu erstellen, die die Todos aus der Datenbank abruft und ein TODOS_LOADED Ereignis ausgibt. Ansichten rufen dann die Aktion loadTodos auf und hören dann das Ereignis TODOS_LOADED und aktualisieren sich dann selbst, indem sie TodoStore.getTodos() anrufen.

Eine andere Alternative ist, keine loadTodos Aktion zu haben, und haben Sie eine TodoStore.getTodos(), die ein Versprechen mit den vorhandenen TODO-Elemente zurückgibt. Wenn der TodoStore die TODO-Elemente bereits geladen hat, werden sie einfach zurückgegeben. Wenn nicht, fragt es die Datenbank ab und gibt die abgerufenen Elemente zurück. In diesem Fall wird das Ereignis TODOS_LOADED nicht ausgegeben, obwohl das Geschäft jetzt die TODO-Elemente geladen hat, da getTodos keine Aktion ist.

function getTodos() { 
    if (loaded) 
     return Promise.resolve($todoItems); 
    else 
     return fetchTodoItemsFromDatabase().then(todoItems) { 
     loaded = true; 
     $todoItems = todoItems; 
     return $todoItems; 
     }); 
} 

Ich bin sicher, viele werden sagen, dass die Fluss Architektur bricht, weil die getTodos Funktion den Speicher Zustand ändert, und speichern Staat sollte nur wenn Aktionen eingesandt vom Dispatcher geändert werden.

Wenn Sie jedoch berücksichtigen, dass der Status für den TodoStore die vorhandenen TODO-Elemente in der Datenbank ist, ändert getTodos keinen Status wirklich. Die TODO-Elemente sind genau gleich, daher muss keine Ansicht aktualisiert oder benachrichtigt werden. Die einzige Sache ist, dass der Speicher jetzt die Daten bereits abgerufen hat, so dass er jetzt im Speicher zwischengespeichert wird. Aus Sicht der Ansicht sollte es nicht wirklich wichtig sein, wie der Store implementiert ist. Es sollte nicht wirklich wichtig sein, ob der Speicher noch Daten aus der Datenbank abrufen muss oder nicht. Alle Ansichten interessieren sich dafür, dass sie den Store verwenden können, um die TODO-Elemente zu erhalten, und dass der Store sie benachrichtigen wird, wenn neue TODO-Elemente erstellt, gelöscht oder geändert werden.

Daher sollten Ansichten in diesem Szenario nur ToDoStore.getTodos() aufrufen, um sich selbst beim Laden zu rendern, und einen Ereignishandler auf TODO_CHANGE registrieren, um benachrichtigt zu werden, wenn sie sich aufgrund eines Hinzufügens, Löschens oder Änderns selbst aktualisieren müssen .

Was halten Sie von diesen beiden Lösungen? Gibt es andere Lösungen?

Antwort

3

Die Ansichten müssen nicht die Entitäten sein, die loadTodos() aufrufen. Dies kann in einer Bootstrap-Datei passieren.

Es ist richtig, dass Sie versuchen sollten, den Datenfluss auf Aktionen innerhalb der Dispatch-Payload zu beschränken. Manchmal müssen Sie Daten basierend auf dem Status anderer Speicher ableiten, und dafür ist Dispatcher.waitFor() zuständig.

Was ist ist Flux-like über Ihre fetchTodoItemsFromDatabase() -Lösung ist, dass keine andere Entität Daten in den Speicher setzt. Der Laden aktualisiert sich selbst. Das ist gut.

Meine einzige ernsthafte Kritik an dieser Lösung ist, dass es zu einer Verzögerung beim Rendern führen kann, wenn Sie tatsächlich die ersten Daten vom Server erhalten. Im Idealfall würden Sie einige Daten mit dem HTML senden. Sie sollten auch sicherstellen, dass die Daten der Filialen in der Methode getInitialState() der Controller-Ansichten aufgerufen werden.

0

Hier ist meine Meinung dazu, ganz in Ihrer Nähe.

  • Ich halte den Zustand meiner Anwendung in Store über Immutable.Record und Immutable.OrderedMap von Immutable.js
  • Ich habe eine Top-Controller-View-Komponente, die seinen Zustand aus dem Store.

Etwas wie die folgenden:

function getInitialState() { 
    return { 
     todos: TodoStore.getAll() 
    } 
} 
  • TodoStore.getAll Methoden werden die Daten vom Server über eine APIUtils.getTodos() Anforderung abrufen, wenn es intern ist _todos Karte leer ist. Ich befürworte für lesen Daten ausgelöst in Store und schreiben Daten ausgelöst in ActionCreators.
  • Durch die Zeit, die Anforderungsverarbeitung ist, wird meine Komponente ein einfachen Laden Spinner oder so ähnlich
  • macht Wenn die Anforderung löst, APIUtils Trigger eine Aktion wie TODO_LIST_RECEIVE_SUCCESS oder TODO_LIVE_RECEIVE_FAIL über den Status der Antwort abhängig
  • Mein TodoStore Willen auf diese Aktion reagiert, indem er seinen internen Zustand zu aktualisieren (bevölkern es interne Immutable.OrderedMap mit Immutable.Record von Aktion Nutzlasten erstellt.

Wenn Sie ein Beispiel durch eine grundlegende Implementierung sehen wollen, nehmen Sie ein Klo k bis this answer about React/Flux and xhr/routing/caching.

0

Ich weiß, es ist ein paar Jahre her, seit das gefragt wurde, aber es hat die Fragen, mit denen ich diese Woche zu kämpfen habe, perfekt zusammengefasst. Um anderen zu helfen, die auf diese Frage stoßen könnten, habe ich diesen Blogpost gefunden, der mir sehr geholfen hat von Nick Klepinger: "ngrx and Tour of Heroes".

Es ist speziell mit Angular 2 und @ ngrx/speichern, aber beantwortet Ihre Frage sehr gut.