I'm fairly new to angularJS, but wrapping up a project and trying to clean up some code by moving a lot of business logic from my controller into a service call.
Currently my three factory service ($resource) calls all work correctly and the results are combined in the controller. But I am not having luck moving all this logic into the service call and returning the combined object, an array.
Here is a much simplified version of my project:
var Myservices = angular.module('Myapp');
Myservices.factory('ResourceA', ['$resource',
function($resource) {
return $resource('/api/resourcea');
}
]);
Myservices.factory('ResourceB', ['$resource',
function($resource) {
return $resource('/api/resourceb');
}
]);
Myservices.factory('ResourceC', ['$resource',
function($resource) {
return $resource('/api/resourcec');
}
]);
Myservices.factory('Results', ['ResourceA', 'ResourceB', 'ResourceC',
function (ResourceA, ResourceB, ResourceC) {
var resourcea, resourceb, resourcec;
var results = [];
return {
get: function() {
ResourceB.query().$promise.then(function(data) { // these calls all work
resourceb = data;
});
ResourceC.query().$promise.then(function(data) {
resourcec = data;
});
ResourceA.query().$promise.then(function(data) {
resourcea = data;
// other code here combines above resource calls and
// populates results[] array successfully ...
//
return results; // this is loaded correctly, but I can't return it
});
}
}
}]);
In debugging through this, I do indeed have an array of results in 'results'.
Now back in my controller I have the following code (simplified for your reading pleasure):
Myapp.controller('MyCtrl',['$scope', '$http', '$log','Results',
function($scope,$http,$log, Results){
// lot of initialization stuff here
// I don't know the correct call to get the 'results' array from my service back to my controller
// these all produce errors
Results.query().$promise.then(function(data){ //Object doesn't support property or method 'query'
$log.info('Results: ' + data);
}
Results.query().then(function(data){ //Object doesn't support property or method 'query'
$log.info('Results: ' + data);
}
Results.get().$promise.then(function(data){ //Unable to get property '$promise' of undefined or null reference
$log.info('Results: ' + data);
}
Results.get().then(function(data){ //Unable to get property 'then' of undefined or null reference
$log.info('Results: ' + data);
}
Results.get().success.then(function(data){ //Unable to get property 'success' of undefined or null reference
$log.info('Results: ' + data);
}
}]);
As you can see, I have begun to resort to 'Trial and Error' with more of the latter than I desire. I am obviously missing something, but feel I am close.
Thank you in advance for any suggestions.
Cheers, Dan
It is not clear how you combine the results from ResourceA.query()
, ResourceB.query()
and ResourceC.query()
, but the approach is probably incorrect, since the data are fetched asynchronously and you seem to be trying to combine them synchronously.
Furthermore, you can't call Results.query()
, because there is no such method.
You need to combine the A, B, C results asynchronously.
This also means you can't return results
from your Results.get()
method. You need to return a promise that gets resolved once the data is fetched and combined.
You can combine multiple promises into one using $q.all()
.
E.g.:
Myservices.factory('Results', function ($q, ResourceA, ResourceB, ResourceC) {
var results = [];
return {
get: function () {
var dataA = ResourceA.query();
var dataB = ResourceB.query();
var dataC = ResourceC.query();
var resultsPromise = $q.all({
a: dataA.$promise,
b: dataB.$promise,
c: dataC.$promise
}).then(function (data) {
var results = [].concat(dataA).concat(dataB).concat(dataC);
return results;
}).catch(function (error) {/* Handle the error... */});
return resultsPromise;
}
};
});
Then, you can use it in your controller like this:
Myapp.controller('MyCtrl', function ($scope, $http, $log, Results) {
...
Results.get().then(function (results) {
$scope.results = results;
$log.info(results);
});
});