2013-08-28 81 views
33

我在Angular中有一项服务,它使用我的API获取用户信息并将其提供给我的控制器。它的成立是这样的:Force AngularJS服务在加载控制器之前返回数据

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 

在我的控制器,我把它给喜欢:

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

这是没有返回数据,而如果我把同样的服务功能的控制器本身它仅返回精细。我在这里错过了什么?以前从未在Angular中使用过DI /服务,所以在某个地方可能是一个简单的错误。

我需要确保服务返回数据之前控制器加载。如何完成这项工作

+6

你可以简化你的console.logs,像这样: 'console.log('user info is',userInfo);' –

+0

@EddieMongeJr真的吗?不知道,谢谢。 – Jascination

回答

42

可以使工厂恢复这样一个承诺:

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 

而在你的控制器,做

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

这可以保证,只要你使用的服务,它总是给你数据同步,您不必在加载控制器之前加载任何数据。

+6

承诺可以直接分配给'$ scope'。当承诺解决时,Angular会自动更新视图。 –

+0

这让它工作。干杯。 – Jascination

+6

请注意,承诺不会自动以角度1.2+展开。 –

17

您的userInfo服务必须返回由$http返回的承诺。该承诺将被注入到您的控制器中,并且只要承诺成功解决,该视图就会被更新。


如果您不希望以便在所有前userInfo做出决议呈现这样做,你应该设置你的路线上resolve财产,并有注入你的服务:

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

然后,只需注入userInfoData代替userInfo服务。

+1

我需要这些数据可用于所有控制器/路由,是否有一种特殊的方式来注入一次,因此我不必为每条路由执行20次以上的操作? – Jascination

+0

@Jascination - 不是我所知道的。我认为你只需要为你需要的所有路由设置那个'resolve:resolveUserInfo'。 –

+0

有趣。我试过你的解决方案,但它仍然在做同样的事情 - 在数据解析之前加载控制器。我知道这可能不应该是由于'resolve',我假设这是一个异步/回调问题,因为'resolveUserInfo'函数在返回前没有完成加载数据。 – Jascination

0

您可以将资源对象分配给您的变量一样, 回报$ http.get(URL)

0

我所面临的,我不得不使用$资源将数据加载到一个服务,并得到了同样的问题该数据转化为控制器$ scope。 我不想直接返回承诺,然后在控制器中使用解析器(如@zsong写的),但是要一次性完成所有的魔法,并使用直接将$ promise作为@作为@约瑟夫·西尔伯指出,所以这里是我做过什么:

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

和Controller像这样使用它:

userInfo($scope); 

没有多大的改善,但它让我在我的控制器更清晰的语法,希望它在三年后能够帮助!

相关问题