在Angular中$ http请求之后未在链接函数中定义的数据

时间:2015-06-24 21:04:37

标签: javascript angularjs

我有以下代码。

controller.js

angular.module('LiveAPP.main',['LiveAPP.factory'])
.controller('mainCtrl', ['$scope','$http', '$location','dataFactory',mainCtrl])

.directive('ratehome',function(){
  return {
    restrict:"E",
    template: "<div id='rateYo'></div>",
    link: function(scope, ele, attrs){
      console.log("NEW",scope.recentArtist)
    }
  }
})


function mainCtrl($scope,$http,$location,dataFactory){

  $scope.getRecentArtists = function(){
     return $http({
        method: 'GET',
        url: '/artistsearch',
        params: {getArtist: "all"}
    }).then(function(recent){
      $scope.recentArtist = recent.data

    })
  };

  $scope.getRecentArtists();

  $scope.recentArtist = ""

  $scope.$watch('recentArtist',function(newValue,oldValue){
    $scope.recentArtist = newValue

  })

}    

的test.html

<ratehome></ratehome>
<ratehome></ratehome>
<ratehome></ratehome>

这里发生的是我的控制器实例化(路由设置正确)有一个$http GET请求响应我需要的数据被分配给$scope.recentArtist。我希望在我的链接功能中可以访问这些数据,但事实并非如此。在发送此请求之前,我感觉我的指令正在编译。有没有办法解决?对我来说奇怪的是,当我console.log(scope)并在Chrome开发者工具中查看我的数据时。然而,当我console.log(scope.recentArtist)时,它的空白与控制器中的状态相似。我以为我可以在我的指令中制作$http.get,但这对我来说似乎有些尴尬。

我几天来一直遇到这个问题,希望有人可以帮帮我。

3 个答案:

答案 0 :(得分:1)

由于您的指令未使用隔离的str = "Revenue - Costs * (1 + Profitpercentage)" p str.scan(/[A-Za-z]+/) # => ["Revenue", "Costs", "Profitpercentage"] ,这意味着您可以直接访问指令中的控制器范围。我建议你将scope置于指令$watch内,而不是你的控制器。这会让你知道ajax已经完成并且数据已经改变了。你在link函数中得到了那些改变的值。

<强>代码

watcher

答案 1 :(得分:1)

如果您使用angular ui-router,也可以使用resolve。使用resolve,您可以在控制器启动之前执行$http

  

您可以使用resolve为控制器提供自定义状态的内容或数据。 resolve是一个可选的依赖关系图,应该注入控制器。

     

如果这些依赖项中的任何一个是promise,它们将被解析并在实例化控制器之前转换为值,并且   $ stateChangeSuccess事件被触发。

     

来自docs

请查看下面的演示或此jsfiddle

angular.module('demoApp', ['ui.router'])
    .config(function ($urlRouterProvider, $stateProvider) {
    $urlRouterProvider.otherwise('/');
    $stateProvider.state('home', {
        url: '/',
        template: '<ratehome></ratehome><ratehome></ratehome><ratehome></ratehome>',
        controller: 'mainCtrl',
        resolve: {
            artists: function (artistsService) {
                console.log('Resolve');
                return artistsService.get(); //'/artistsearch',//artistsService.get();
            }
        }
    });
})
    .controller('mainCtrl', ['$scope', '$http', '$location', 'artists', MainCtrl])

    .directive('ratehome', function () {
    return {
        restrict: "E",
        template: '<div id="rateYo"><ul><li ng-repeat="artist in recentArtist">{{artist}}</li></ul></div>',
        link: function (scope, elem, attrs) {
            console.log("NEW", scope.recentArtist);
        }
    }
})

    .factory('artistsService', function ($http) {
    return {
        get: function () {
            console.log('getting');
            return $http({
                method: 'GET',
                url: 'http://crossorigin.me/http://www.mocky.io/v2/558b30615f3dcbc414067170', //'/artistsearch',
                //params: {getArtist: "all"}
            }).then(function (recent) {
                //console.log(recent);
                return recent.data;
            });
        }
    };
});

function MainCtrl($scope, $http, $location, artists) {

    $scope.recentArtist = artists;
    console.log('ctrl', artists);    

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<div ng-app="demoApp">
    <div ui-view=""></div>
</div>

答案 2 :(得分:0)

您的链接功能在$ http响应回来之前正在运行,因为您怀疑。您可以按using $broadcast and $on

等待它
angular.module('LiveAPP.main',['LiveAPP.factory'])
    .controller('mainCtrl', ['$scope','$http', '$location','$rootScope','dataFactory',mainCtrl])
    .directive('ratehome',function(){
        return {
            restrict:"E",
            template: "<div id='rateYo'></div>",
            link: function(scope, ele, attrs){
                scope.$on('artistLoaded', function(){
                    console.log("NEW",scope.recentArtist);
                });
            }
        };
    });


function mainCtrl($scope,$http,$location,$rootScope,dataFactory){
    $scope.getRecentArtists = function(){
        return $http({
            method: 'GET',
            url: '/artistsearch',
            params: {getArtist: "all"}
        }).then(function(recent){
            $scope.recentArtist = recent.data
            $rootScope.$broadcast('artistLoaded');
        });
    };

    $scope.getRecentArtists();
    $scope.recentArtist = "";

    $scope.$watch('recentArtist',function(newValue,oldValue){
        $scope.recentArtist = newValue
    });
}  

这样,在返回并设置

响应之前,代码才会运行