Reputation: 57
It seems that factory methods execution priority is the highest, so that callbacks has no data to deal with. What is the best way to make this work?
I got this kind of factory
app.factory('jsonService', function($http) {
return {
getDistricts: function(callback) {
$http.get('data/districts.json').success(callback);
},
getLocations: function(path,callback) {
$http.get('data/'+path+'.json').success(callback);
}
};
});
And controller
var app = angular.module('sandbox', []);
app.controller('sandboxCtrl',function ($scope,jsonService) {
//This one works
$scope.init1= function(){
jsonService.getDistricts(function(data){
$scope.districts = data;
$scope.currentDistrict = $scope.districts[0].name;
jsonService.getLocations($scope.currentDistrict,function(data){
$scope.locations1 = data;
})
});
};
$scope.init1();
//This one does not
$scope.init2= function(){
jsonService.getDistricts(function(data){
$scope.districts = data;
$scope.currentDistrict = $scope.districts[0].name;
})
jsonService.getLocations($scope.currentDistrict,function(data){
$scope.locations1 = data;
});
};
$scope.init2();
});
Here is working plunker
Upvotes: 1
Views: 222
Reputation: 64853
Angular has an implementation of promises named $q (documentation) that you should read up upon.
There is a race condition due to the async nature of http calls. Please review the updated code linked to below that shows an example of your code running (successfully) using promises to handle your two calls in succession.
So upon success of your first call it will call your second service method all without using callbacks thanks to the power of promises.
jsonService.getDistricts()
.success(function(data) {
$scope.districts = data;
$scope.currentDistrict = $scope.districts[0].name;
jsonService.getLocations($scope.currentDistrict)
.success(function(locationData) {
$scope.locations = locationData;
})
});
Promise clarification:
The raw implementation of basic promises uses then
to handle responses and promises returned from $http
add additional methods (success
, error
) that will unpack your data from the response object that you would need to handle if your just use then
.
Upvotes: 1
Reputation: 3642
init1()
is the correct way of doing this. init2()
does work because jsonService.getLocations()
is getting invoked before jsonService.getDistritcs()
completes. The angular $http
service is asynchronous. Since jsonService.getLocations()
depends on data from jsonServicd.getDistricts()
you must wait until .getDistricts()
completes before calling .getLocations()
. One way to do that is to call .getLocations()
within the .getDitricts()
callback, just as you did in init1()
.
Upvotes: 1