webentwicklung-frage-antwort-db.com.de

Erzwingen Sie, dass der AngularJS-Dienst Daten zurückgibt, bevor der Controller geladen wird

Ich habe einen Dienst in Angular, der meine API verwendet, um Benutzerinformationen abzurufen und diese meinen Controllern zur Verfügung zu stellen. Es ist so aufgebaut:

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo'])
  .service('userInfo', function($http, $cookies){
    $http.get('/api/users/' + $cookies.id).
    success(function(data) {
      var userInfo = data.user[0];

      return userInfo;
    });
  }). // other stuff comes after this

In meine Controller füge ich es ein:

function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){
    $scope.user = userInfo;
    console.log('user info is')
    console.log(userInfo);

Dies gibt keine Daten zurück, während ich, wenn ich die gleiche Servicefunktion in den Controller selbst stecke, genau das zurückgibt. Was fehlt mir hier? Sie haben DI/Services noch nie in Angular verwendet, daher könnte es irgendwo einen einfachen Fehler geben.

Ich muss sicherstellen, dass der Dienst Datenzurückgibt, bevorder Controller geladen wird. Wie kann das erreicht werden?

34
JVG

Sie können die Fabrik dazu bringen, ein Versprechen wie folgt zurückzugeben:

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo'])
    .service('userInfo', function ($http, $cookies) {
    var promise = $http.get('/api/users/' + $cookies.id).
    success(function (data) {
        var userInfo = data.user[0];
        return userInfo;
    });
    return promise;
}) // other stuff comes after this

Und in Ihrem Controller

function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){
    userInfo.then(function(data){
        $scope.user = data;
    });
}

Dadurch kann sichergestellt werden, dass Sie bei jeder Verwendung des Dienstes immer die Daten synchron erhalten, und Sie müssen vor dem Laden der Steuerung nicht unbedingt Daten laden.

42
zsong

Ihr userInfo-Service muss das von $http zurückgegebene Versprechen zurückgeben. Dieses Versprechen wird dann in Ihren Controller eingefügt, und die Ansicht wird aktualisiert, sobald das Versprechen erfolgreich gelöst wurde.


Wenn Sie nicht möchten, dass die Ansicht vor der Auflösung von userInfo gerendert wird, sollten Sie eine resolve -Eigenschaft für Ihre Route festlegen und Ihren Dienst dort einfügen:

$routeProvider.when('/profile', {
    templateUrl: 'profile',
    controller: userProfile,
    resolve: {
         userInfoData: function ($q, userInfo) {
             return userInfo;
         }
    }
});

Dann injizieren Sie einfach userInfoData anstelle des userInfo-Dienstes in Ihren Controller.

17
Joseph Silber

Ich hatte das gleiche Problem, bei dem ich Daten mit $ resource in einen Dienst laden musste und diese Daten in Controller $ scope ..__ bekam. Ich wollte das Versprechen nicht direkt zurückgeben und dann einen Resolver im Controller verwenden (wie @zsong schrieb), aber einmal die ganze Magie in den Dienst zu bringen und die Fähigkeit zu verwenden, ein Versprechen direkt einem $ scope zuzuweisen, wie @Joseph Silber darauf hinweist, also habe ich folgendes getan:

return function($scope){promise.then(function(data){$scope.user = data})};

Und benutzte es in der Steuerung so:

userInfo($scope);

Keine große Verbesserung, aber es hat mir eine klarere Syntax in meinen Controllern ermöglicht. Ich hoffe, es hilft auch drei Jahre später!

0
PaulCo

Sie können das Ressourcenobjekt Ihrer Variablen wie folgt zuordnen Return $ http.get (url)

0