I'm loading json data into my app, but it always return undefined. After many tests and changes I found out that the service runs after the controller or at least that's what I think it does.
Service
.factory('personService', function($http) {
return {
getPersons: function() {
return $http.get('/persons.php');
}
}
})
Controller
.controller('personsCtrl', function($scope, personService) {
var promise = personService.getPersons();
promise.then(
function(response) {
$scope.persons = response.data;
console.log(response.data);//first
},
function(response) {
console.log('failed loading');
});
console.log($scope.persons); //last
})
Console prints out the //last before the //first, which means it probably runs before it gets the data from the json file.
Console
undefined
[object object object]
Anyone has any idea what I'm doing wrong here? Thanks.
Your code is perfectly fine and there's no need to change it.
I wouldn't follow Vamsi's advice - sorry man - as it's always better to resolve the promise in the controller instead of resolving it immediately.
The reason for this is at some point you might want to chain it (getPersons
) with other promises from other services:
personService.getPersons()
.then(function(result){
return service2.doSomething(result);
})
.then(function(result){
return service3.doSomeOtherThing(result);
})
.then(function(result){
return service4.doLastThing(result);
})
.catch(function (reason) {
console.log(reason);
})
.finally(function(){
// always executed.
});
if you look at this bit of code you can see a typical promise chaining where each service uses the result from the previous promise and returns it to the following branch of the chain.
If something wrong happens you would be able to catch
the error and move on.
Going back to your problem:
.controller('personsCtrl', function($scope, personService) {
var promise = personService.getPersons();
promise.then(
function(response) {
$scope.persons = response.data;
console.log(response.data);//first
},
function(response) {
console.log('failed loading');
});
console.log($scope.persons); //last
});
promises can be delayed, especially when dealing with $http
requests.
console.log($scope.persons); //last
is going to be called immediately cause the code is executed from the top to the bottom and the promise - again - might have some delay.
In a real case scenario you would define an empty array in your controller:
.controller('personsCtrl', function($scope, personService) {
$scope.persons = [];
});
call a service and wait until the services returns the data:
.controller('personsCtrl', function($scope, personService) {
$scope.persons = [];
personService.getPersons()
.then(function(result){
$scope.persons = result.data;
});
});
and populate your $scope.persons
which would be bound to the UI and update the interface.
If you need to to some other things before you populate $scope.persons
you can chain with another promise.
If you want to dig deeper into promises I would suggest to read this article which is the best explanation I've found.
If you're interested to follow some really good guidance about controllers, promises and the way to build services John Papa Style Guide.