AngularJS-Ressourcenversprechen

75

Ich habe einen einfachen Controller, der $ resource verwendet:

 var Regions = $resource('mocks/regions.json');

 $scope.regions = Regions.query();

Ich benutze diesen Controller in einer Direktive (in der Link-Funktion)

var regions = scope.regions;

Aber Regionen sind undefiniert. Es ist ziemlich logisch, dass der Anruf asynchron ist.

Meine Frage ist, wie ich warten kann, bis das Ergebnis und die Regionen ein Array mit allen Daten sind.

UPDATE : 

Hier die Definition der Richtlinie

app.directive('ngMap', function() {
  return {
    restrict: 'EA',
    replace: 'true',
    scope: {

    },
    template: '<div id="map"></div>',
    controller: 'AccordMapCtrl',
    link: function(scope, element, attrs) {
      var regions = scope.regions;
      console.log(regions);

      for (var region in regions) {}
    };
  });
Thomas Pons
quelle
Zeigen Sie die von Ihnen erstellte Direktivendefinition an?
Chandermani
Es ist geschafft, ich habe die Richtlinie hinzugefügt
Thomas Pons
Ich hatte das gleiche Problem und verwendete die Lösung von @AndreyPushkarev innerhalb der Link-Funktion. Grundsätzlich befindet sich die gesamte Logik in der Verknüpfungsfunktion im Inneren $promise.then(function(result){...});.
Elliot Vargas
Nur um sicherzugehen, dass ich kein Missverständnis habe - der "Rückruf" -Ansatz zur Lösung dieses Problems funktioniert technisch genauso gut wie der "Versprechen" -Ansatz, richtig? (Ich bevorzuge die Syntax von Versprechungen, aber es scheint mir, dass Rückrufe technisch das gleiche erreichen würden)
Rinogo
Ja, Sie haben die Wahl zwischen $ versprechen.dann oder einem einfachen Rückruf. Der $ Versprechen Ansatz ist mehr "semantisch", denke ich
Thomas Pons

Antworten:

185

Wenn Sie eine asynchrone Methode verwenden möchten, müssen Sie die Rückruffunktion von $ versprechen verwenden. Hier ist ein Beispiel:

var Regions = $resource('mocks/regions.json');

$scope.regions = Regions.query();
$scope.regions.$promise.then(function (result) {
    $scope.regions = result;
});
Andrey Pushkarev
quelle
32
Warum die beiden Zwischenaufgaben machen? Wenn, wie ich erwarte, Regionsnicht woanders verwendet wird, dann resource('mocks/regions.json').query().$promise.then(function (result) { $scope.regions = result; });würde sicherlich die Arbeit erledigen.
Roamer-1888
18
kann hilfreich sein, Zwischenzuweisungen beim Debuggen von Code zu haben
Josh Diehl
1
Aus $ resource docs: ... Das Aufrufen einer $ resource-Objektmethode gibt sofort eine leere Referenz zurück ... Dies ist ein nützlicher Trick, da die Ressource normalerweise einem Modell zugewiesen wird, das dann von der Ansicht gerendert wird. Wenn ein leeres Objekt vorhanden ist, wird es nicht gerendert. Sobald die Daten vom Server eingehen, wird das Objekt mit den Daten gefüllt und die Ansicht rendert sich automatisch neu und zeigt die neuen Daten an.
Jarz
OK, aber verhält sich meine Version ohne Zwischenzuweisungen nicht gleich? Bis zur $scope.regions = resultAusführung wird nichts gerendert .
Roamer-1888
@ Roamer-1888 Ich stimme Ihnen zu, dass Ihr Code der akzeptierten Antwort in dieser einfachen Übung funktional entspricht. Ich arbeite jedoch an einer komplexeren App, die Daten aus mehreren Tabellen an die Ansicht zurückgibt. Um meinen Code sauberer zu halten und das DRY-Prinzip zu implementieren, habe ich das Aufrufen des $ resource-Objekts in eine wiederverwendbare Factory abstrahiert. Ich übergebe den eindeutigen Teil des Pfads als Parameter von meinem Controller an die Fabrik und gebe die Daten an meinen Controller zurück. Dazu muss ich Zwischenaufgaben haben, die der akzeptierten Antwort ähneln.
Steveo
36

Wenn Sie beim Ressourcenaufruf ein Versprechen erhalten möchten, sollten Sie es verwenden

Regions.query().$q.then(function(){ .... })

Update: Die Versprechenssyntax wird in aktuellen Versionen geändert

Regions.query().$promise.then(function(){ ..... })

Diejenigen, die abgestimmt haben, wissen nicht, was es war, und die dieses Versprechen zuerst dem Ressourcenobjekt hinzugefügt haben. Ich habe diese Funktion Ende 2012 verwendet - ja 2012.

Mahbub
quelle
Es ist ab 1.1.15 verfügbar. Möglicherweise möchten Sie die Version aktualisieren.
Mahbub
Ich benutze 1.2 RC für echte App. Und es ist eine geschäftskritische App. Ich habe nur einige ausgefallene Dinge ausprobiert, die sie in letzter Zeit hinzugefügt haben. Dieses Ressourcenversprechen wurde letztes Jahr in unserer App in eckiger Form verwendet. Wir haben gerade den Patch hinzugefügt, den ein Typ vorgeschlagen hat, und Angular Team hat "Good to Merge" markiert. Es ist keine große Sache. Wenn Ihnen das wichtig ist, erstellen Sie einen benutzerdefinierten $ http-Wrapper und verwenden Sie ihn wie Ressourcenaufrufe. Sie erhalten dann Versprechen.
Mahbub
Ich verspreche eine Ressource in 1.0.8, es ist nur so, dass die Syntax anders ist :)
Thomas Pons
Ich werde die Antwort posten;)
Thomas Pons
20

Sie könnten auch tun:

Regions.query({}, function(response) {
    $scope.regions = response;
    // Do stuff that depends on $scope.regions here
});
Andreas
quelle
9
Dies ist jedoch die Rückrufsyntax, nicht versprochen?
Erico
0
/*link*/
$q.when(scope.regions).then(function(result) {
    console.log(result);
});
var Regions = $resource('mocks/regions.json');
$scope.regions = Regions.query().$promise.then(function(response) {
    return response;
});
DW.Ding
quelle