2014-10-17 78 views
1

我想在控制器完成剩下的任務之前等待服務$ http結果。 我爲myData測試了一些硬編碼的JSON,它在控制器中是可見的,但只要我試圖用$ http請求填充myData,控制器就不會等待它,只是通過代碼的其餘部分。 Chrome webdevelopper的網絡標籤顯示了該請求的預期結果。

我已經具備以下條件:

var ListerApp = angular.module('ListerApp',[ 
    'ListerAppFilters', 
    'sharedFactoryApp', 
    'sharedServiceApp', 
    'ListerAppController', 
    'infinite-scroll', 
    'angular-inview', 
    'ngRoute' 
]); 

ListerApp.config(['$routeProvider', '$httpProvider', function($routeProvider, $locationProvider) { 
    $routeProvider 
     .when('/list', 
      { 
       templateUrl: '/assets/services/partials/list.html', 
       controller: 'ListerCtrl', 
       resolve : { 
        'sharedServiceAppData': function($sharedServices){ 
         // sharedFactoryAppData will also be injectable in your controller, if you don't want this you could create a new promise with the $q service 
         return $sharedServices.promise(); 
        } 
       } 
      } 
     ); 
}]); 

angular.module('sharedServiceApp', []).service('$sharedServices', ['$http', '$rootScope', '$q', function($http, $rootScope, $q) { 
    var myData = null; 

    return { 
     promise : function() { 
      if (!myData) { 
       $http({method : 'GET', url : '/shop/api/json', params : { 
         end   : $rootScope.endmarkerSyncDataset, 
         page  : 1, 
         per_page : $rootScope.itemsPerPage 
        } 
       }).success(function (data) { 
        myData = data.data_set; 
        //deferred.resolve(data.data_set); 
       }); 

       // I allready tested this and this is OK: myData = {foo : 'bar'}; 
      } 
     }, 
     getShopData: function() { 
      return myData; 
     } 
    }; 
}]); 

(function(){ 
    var appController = angular.module('ListerAppController', []); 

    appController.controller('ListerCtrl', ['$scope', '$rootScope', '$http', '$filter', '$timeout', '$sharedFactories', '$sharedServices', 
     function($scope, $rootScope, $http, $filter, $timeout, $sharedFactories, $sharedServices) { 
      $scope.items = $sharedServices.getShopData(); 
      console.log($scope.items); // return myData -> null 
     } 
})(); 

回答

3

我已經這樣做了一堆倍這裏就是我平時做的routeProvider我的決心對象,需要確保你適當地返回所有的承諾以便路由更改等待解析屬性。

$routeProvider 
    .when('/path', 
     { 
      templateUrl: 'some/path/to/template.html', 
      controller: 'myCtrl', 
      resolve : { 
       'myData': ['mySrvc',function(mySrvc){ 
        return mySrvc.someMethod().then(function(response){ 
         return response.data; 
        },function(){ 
         return {}; 
        }); 
       }] 
      } 
     } 
    ); 

然後,服務:

angular.module('myApp.services').factory('mySrvc',['$http',function($http){ 
    var _url = 'https://someurl.com/path/to/api'; 

    return { 
     someMethod : function(vars){ 
      if(angular.isDefined(vars)){ 
       return $http.post(_url,$.param(vars),{headers:{'Content-Type':'application/x-www.form-urlencoded'}}); 
      }else{ 
       return $http.get(_url); 
      } 
     } 
    }; 
}]); 

然後在控制器你需要對控制器的參數列表的末尾註入的決心參數。

angular.module('myApp.controllers').controller('myCtrl',['$scope','myData',function($scope,myData){ 

}); 

在你的代碼,在routeProvider你從沒有返回值的函數返回的決心對象,嘗試恢復從$http的承諾,然後在成功功能data.data_set值你的服務。

+1

感謝您的幫助。我找到了一些東西,並在下面發佈。你的例子幫助我進一步創建一個API類對象。 – poashoas 2014-10-17 15:02:46

0

我找到了類似$ q.defer,resolve和promise的東西。 它阻止了一切,直到達到「承諾」狀態。

這裏的a link

angular.module('sharedServiceApp', []).service('$sharedServices', ['$http', '$rootScope', '$q', function($http, $rootScope, $q) { 
    var myData = null; 

    return { 
     promise : function() { 
      if (!myData) { 
       var deferred = $q.defer(); 
       $http({method : 'GET', url : '/shop/api/json', params : { 
        end   : $rootScope.endmarkerSyncDataset, 
        page  : 1, 
        per_page : $rootScope.itemsPerPage 
       } 
      }).success(function (data) { 
       myData = data.data_set; 
       deferred.resolve(data.data_set); 
      }).error(function(data, status, headers, config) { 
       deferred.reject("Error: request returned status " + status); 
      }); 
      return deferred.promise; 
     } else { 
      return myData; 
     } 
    }, 
    getShopData: function() { 
     return myData; 
    }, 
    setShopData: function (data) { 
     myData= data; 
    } 
}; 

}]);

+1

因爲'$ http'已經返回一個承諾,所以在這個實例中你確實不需要使用'$ q'。只需從'$ http'調用返回承諾,然後在* success *和* error *函數中確保返回數據或錯誤狀態。 – 2014-10-17 15:34:42

+0

就是這樣!謝謝一堆。這真的幫了我很多。 – poashoas 2014-10-17 17:04:53

+0

當然沒問題,很樂意幫忙。 – 2014-10-20 13:09:42