I can\'t wrap my head around AngularJS\' concept of promises.
I have a provider:
var packingProvider = angular.module(\'packingProvider\',[]);
packi
Try
var packingProvider = angular.module('packingProvider',[]);
packingProvider.provider('packingProvider',function(){
return{
$get: function($http){
return{
getPackings: function(){
return $http.post('../sys/core/fetchPacking.php').then(function(response){
return response.data; // packings
});
}
}
}
}
});
Then
packingProvider.getPackings().then(function(packings){
console.log(packings);
});
Main idea: you need to return the promise object from the getPackings function. Not sure if you can make the call to it synchronous but it's almost definitely not a great idea to do so. Also, if you want to make "packings" a model object on your controller and use for a two-directional binding, you can safely assign the promise object, which Angular will resolve as soon as data comes through:
$scope.packings = packingProvider.getPackings();
UPDATE
As of 1.2.0-rc.3 promise unwrapping has been deprecated (https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-rc3-ferocious-twitch-2013-10-14) , so the line of code above will not result in a two-directional binding any more.
The return value from within your then
method isn't returning when you think it is; it's returning later.
In the statement var packings = packingProvider.getPackings();
the return value is undefined because the promise returned from $http
is asynchronous. That means that the call to $http.post
happens, does not complete, then your function returns. In JS functions that don't return anything return undefined. The post
call completes later and executes return packings;
which gets returned to nowhere.
The getPackings
method should probably return the promise from $http.post
directly. That way any code that wants to use this method can call then
on the promise directly and set the value the way it needs to. In a controller you could assign that promise directly to the $scope
and use it in your view. Here's a nice post that explains that particular feature: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
Incidentally, it looks like you've got a long-winded service declaration there; any reason not to shorten it to something like this?
var module = angular.module('packing', []);
module.service('packing', function($http) {
return {
getPackings: function() {
return $http.post('../sys/core/fetchPacking.php');
}
};
});
I'm relatively new to AngularJS but I don't see any gain in all that typing. ( =
There are a ton of resources available that show you how to use Deferreds/Promises with jQuery. Try a search for those and that may help you get over this hurdle. Afaik, the AngularJS promises are the same as the jQuery promises.
A jQuery promise is used something like this:
var getPackings = function() { return $.get('../sys/core/fetchPacking.php'); };
var packings;
$.when(getPackings()).then(function(data){ packings = data; console.log(packings) });
Keep in mind though that jQuery ajax calls have functions such as .done, .success, etc.. that would replace the generic Deferreds' .when().then() functions.
In the above jQuery method, you can see that we have to set the data and output it in the .then() function, because you cannot guarantee that the asynchronous process is done anywhere else. So ideally you would call to whatever function continues your processing in the .then() function, like so:
$.when(myAsyncFunc()).then(myAppCanContinue(dataReturnedByAsyncFunc));
Angular is going to follow the same logic. If you understand the above, it should be easier to understand how to accomplish this in Angular. Also, check out this article that gives simple examples: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
In order to get your code to work, you will need to do something like this:
packingProvider.provider('packingProvider',function(){
return{
$get: function($http){
return{
getPackings: function(){
return $http.post('../sys/core/fetchPacking.php');
}
}
}
}
});
var packings = packingProvider.getPackings();
packings.then(function(data) { console.log(data)});