0

Ich habe einen API-Aufruf, der funktioniert, aber ich würde es gerne auf mehreren Controllern verwenden, also habe ich es zu seinem eigenen Dienst verschoben. Ich stoße auf etwas, das wie ein klassisches Scope-Problem aussieht, oder auf ein Missverständnis des Digest-Zyklus von Angular.AngularJS, wie verwende ich einen Service, um HTTP-Daten zu erfassen und an meinen Controller zu binden?

'use strict'; 
myApp.factory('Stuff',['$http', function ($http) { 
    var Stuff = {}; 
    Stuff.data = {}; 
    Stuff.api = 'http://localhost:8080/api/'; 
    Stuff.getStuff = function() { 
    var http_stuff_config = { 
     method: 'GET', 
     url: Stuff.api + 'stuff/' 
    }; 
    $http(http_stuff_config).then(function successCallback(response) { 
     Stuff.data = (response.data); 
     console.log(Stuff.data); // Returns populated object. 
    },function errorCallback(response) { 
     console.log(response.statusText); 
    }); 
    }; 
    Stuff.getStuff(); 
    console.log(Stuff.data); // Returns empty object. 
    return Stuff; 
}]); 

myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) { 
    $scope.stuff = Stuff; 
    console.log($scope.stuff.data); // Returns empty object. 
    $scope.stuff.getJobs(); 
    console.log($scope.stuff.data); // Returns empty object. 
}]); 

Hier ist der große Hinweis. Die wesentliche Leistung von oben, in Ordnung ist ...

  1. leeres Objekt (in Dienst nach dem Aufruf-Methode)
  2. leeres Objekt (im Regler vor dem Aufruf-Methode)
  3. leeres Objekt (in der Steuerung nach dem Aufruf der Methode)
  4. besiedeltes Objekt (in Methodenausführung von Dienst)
  5. bevölkerten Objekt (in der Ausführung von Verfahren Controller)

So irgendwo zwischen dem Umfang der getStuff() -Methode und Angulars Reihenfolge der Operationen, mache ich etwas bemerkenswert dummes. Vielen Dank im Voraus.

+0

hat meinen Sie $ http Daten zu erfassen? –

Antwort

1

Sie müssen Rücksendungen zu Ihrem Service hinzufügen, sonst wird das Versprechen nicht an den Controller zurückgegeben. Es ist nicht gut, die Renditen einfach in Ihren Diensten zu speichern UND das Ergebnis NICHT an den Controller zu senden.

Dies ist eine schlechte Vorgehensweise, da jeder Benutzer, der die Daten des Dienstes aktualisiert, $scope.$watch auf den Dienst anwenden muss, um nach Updates zu suchen. Dies kann in großen Apps sehr teuer sein.

Die beste Idee ist es, die Daten an den anrufenden Controller zurückzukehren und lassen Sie den Controller Zugriff es über das Versprechen service.getthing().then(function(result){});

myApp.factory('Stuff',['$http', function ($http) { 
    var Stuff = {}; 
    Stuff.data = {}; 
    Stuff.api = 'http://localhost:8080/api/'; 
    Stuff.getStuff = function() { 
    var http_stuff_config = { 
     method: 'GET', 
     url: Stuff.api + 'stuff/' 
    }; 
    return $http(http_stuff_config).then(function successCallback(response) { 
     return response.data; 
     console.log(Stuff.data); // Returns populated object. 
    },function errorCallback(response) { 
     console.log(response.statusText); 
    }); 
    }; 
    Stuff.getStuff(); 
    console.log(Stuff.data); // Returns empty object. 
    return Stuff; 
}]); 




myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) { 
    $scope.stuff = Stuff; 
    console.log($scope.stuff.data); // Returns empty object. 
    $scope.stuff.getJobs().then(function(result) {$scope.stuff = result; console.log(result);}); 
    console.log($scope.stuff.data); // Returns empty object. 
}]); 
+0

Genau das habe ich gebraucht. Vielen Dank. –

0

daran erinnern, dass $scope.stuff.getJobs() ist async

(dh Sie können nicht wirklich console.log($scope.stuff.data) auf der nächsten Zeile aufrufen und die Daten erhalten)

Nun, wenn Sie einen Blick hatte, mit so etwas wie <span ng-bind="stuff.data.property"> Sie es sehen konnte, funktionieren gut, weil die Ansicht sich selbst aktualisiert, wenn die Async-Funktion ausgeführt wird. (Dies ist ein Teil von Winkel)

0

Ich empfehle Ihnen, das Ergebnis nicht im Service selbst (Stuff.data) zu speichern. Geben Sie Ihre Daten einfach in der Funktion "getStuff" zurück und lassen Sie stattdessen den Bereich des AppControllers die Daten speichern.

0

(wenn Sie es nicht zwischenspeichern müssen, dies können wir später reden) Sie müssen verstehen, dass wenn Sie $ http ausführen, es eine AJAX-Anfrage macht. daher wird es nicht sofort ein Ergebnis zurückgeben.

Daher, wenn Sie versuchen, die Daten aus $ scope.stuff.getJobs() zu verwenden; Unmittelbar nach dem Aufruf dieser Funktion erhalten Sie wahrscheinlich nichts.

Was Sie tun sollten, ist, dass Ihre Stuff.getJobs() ein Versprechen zurückgibt und Sie mit promise.then (Ihrem eigenen Erfolgshandler) die zurückgegebene Antwort korrekt behandeln.

Ich habe Ihren Code ein wenig aufgeräumt. Das Folgende ist ein laufendes Beispiel Ihres Codes, der Daten von Yahoo Weather API abruft.

Sie können damit auf CODEPEN spielen.

html:

<div ng-app="myApp" ng-controller="appController"> 
    <p>{{data}}</p> 
</div> 

JS:

var myApp = angular.module("myApp", []); 

myApp.factory('Stuff',['$http', function ($http) { 
    var Stuff = {}; 
    Stuff.data = {}; 
    //sample yahoo weather api 
    Stuff.api = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys'; 

    Stuff.getData = function() { 
    var http_stuff_config = { 
     method: 'GET', 
     url: Stuff.api + 'stuff/' 
    }; 
    return $http(http_stuff_config); 
    }; 

    return Stuff; 
}]); 

myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) { 
    $scope.data = "$http service not ran"; 

    var uncompletedAjaxCall = Stuff.getData(); 
    uncompletedAjaxCall.then(
    function(responseData){ 
     $scope.data = responseData; 
    }, 
    function(errorMsg){} 
); 

}]);