Wie kann man ein Versprechen bestehend aus verschachtelten Modellen in EmberJS mit EmberData zurückgeben?

8

Umgebung

%Vor%

Modell

Ich habe meinen Anwendungsfall vereinfacht, damit die Frage leichter zu verstehen und zu beantworten ist. Nehmen wir an, wir haben 3 Modelle: Country , Region und Area :

%Vor%

Erwartete Ergebnisse

Der Model-Hook der Route sollte ein Array von Objekten zurückgeben. So:

  

Hinweis: Die Einrückungen sind only , um das Beispiel lesbarer zu machen.

%Vor%

Aktueller Ansatz

%Vor%

Fehler

Ich bekomme Error while loading route: TypeError: Object [object Array] has no method 'then' , was offensichtlich von diesem Code herrührt:

%Vor%

Aber das sollte das wirkliche Problem zeigen, das ich habe:

Das Problem

Ich brauche countries aufgelöst, um regions zu erhalten, was wiederum die areas erfordert. Ich habe die Funktionen RSVP.hash und RSVP.all überprüft, die offizielle API gelesen und dieses Gespräch verfolgt. Allerdings schaffe ich es nicht, den richtigen Code zu erstellen, um Versprechen zu verketten, und im letzten then modifiziere das zurückgegebene Ergebnis, um meine Erwartungen zu erfüllen.

Abschließende Gedanken

Mir wurde gesagt, dass das Laden von Daten wie dieser viele HTTP-Anfragen verursachen kann und wahrscheinlich würde dies besser durch Sideloading gelöst werden, aber:

  • In diesem Moment verwende ich FixturesAdapter , also sind HTTP-Anfragen kein Problem
  • Ich möchte RSVP wirklich verstehen und verspricht

Deshalb ist es mir wichtig, herauszufinden, wie dies richtig gemacht werden sollte.

Bearbeiten 1: Änderungen übernehmen, die von kingpin2k

Ich habe ein JSBin für mein Beispiel mit den von kingpin2k's anwser vorgeschlagenen Änderungen erstellt.

Während der Code funktioniert, sind die Ergebnisse ... unerwartet :

  • Im countries -Array habe ich sowohl country als auch region Objekte gefunden. Warum?
  • Die Objekte country und region scheinen geladen zu sein, die Bereiche jedoch nicht (siehe Konsolenprotokoll in JSBin). Warum?

Edit 2: Erklärung des unerwarteten Verhaltens von Edit1.

So habe ich endlich bemerkt, wo ich vom rechten Weg von Ember abirrte. Kingpin2k's anwser war ein großer Schritt vorwärts, aber es enthält einen kleinen Fehler:

%Vor%

Also ... jetzt habe ich endlich alle Objekte korrekt aufgelöst (Länder, Regionen, Gebiete) und kann meine Arbeit fortsetzen:)

EDIT 3: Arbeitslösung in diesem JSBin !

    
loostro 21.04.2014, 22:10
quelle

2 Antworten

12

Der Trick besteht darin, dass Sie bestimmte Versprechen lösen müssen, bevor Sie auf die Eigenschaften dieser Datensätze zugreifen können. Ember.RSVP.all benötigt ein Array von Versprechen. Ember.RSVP.hash nimmt einen Hash von Versprechen. Leider sind Sie in der Situation, wo Sie Ihre Versprechen nicht aufbauen können, bis die vorherigen Versprechen gelöst sind (a la, Sie wissen nicht, welche regions zu bekommen sind, bis die countries aufgelöst sind, und Sie nicht wissen welche areas bekommen bis die regions aufgelöst sind). In diesem Fall haben Sie wirklich eine Reihe von Versprechen zu holen (wenn auch Arrays von Versprechen auf jeder Ebene). Ember weiß zu warten, bis sich das tiefste Versprechen aufgelöst hat und diesen Wert als Modell zu verwenden.

Jetzt müssen wir so tun, als ob regions und area async sind, wenn sie es nicht sind, erzählen Sie Ember Data, dass die Information in der Anfrage mit country enthalten sein wird, oder in der Anfrage mit region und diese Sammlungen sind keine Versprechen, also würde der Code, den ich unten eingefügt habe, nicht funktionieren.

%Vor%

Da dies so aussieht, als ob Sie Ember Data verwenden würden, würde ich einfach this.store.find('country') zurückgeben und Ember Data die Daten holen lassen, wenn es verwendet wird ... Diese Vorlage würde ohne all diesen Versprechenscode funktionieren, und würde füllen, wie Ember Data die Versprechungen selbst erfüllt (es wird die Daten anfordern, sobald es sieht, dass Sie versucht haben, die Daten zu verwenden, gute alte Lazy Loading).

%Vor%     
Kingpin2k 22.04.2014, 02:28
quelle
4

Was Sie stattdessen tun könnten:

Wenn Sie hier sind, machen Sie wahrscheinlich den gleichen Fehler wie ich :)

Wenn Sie einen komplizierten Baum von Objekten benötigen, um Ihre Route anzuzeigen, können Sie auch:

  • Wenn Sie RESTAdapter verwenden, können Sie Daten in einer HTTP-Anfrage seitenweise laden.
  • Wenn Sie FixturesAdapter (z. B. in der Entwicklungsphase) mit einer festen Datenmenge verwenden, können Sie zu LocalStorageAdapter wechseln - wenn Sie ein Modell anfordern, lädt es alle zugehörigen Modelle. Also wird es so einfach sein wie ein einfacher this.store.find('mymodel', model_id)

Allerdings lasse ich den ursprünglichen anwser als "akzeptiert" markiert, da er die ursprüngliche Frage tatsächlich beantwortet, und diese Antwort ist nur eine Anmerkung für zukünftige Referenzen / andere Benutzer.

    
loostro 24.04.2014 12:06
quelle