I'm writing an Angular.js service to pull some JSON
feeds. Initially, the service does not know which/how many resources to request; they are dependent on ids returned by a another request.
I'm having a headache chaining the $http
service requests together. Is there a commonly used pattern to do this?
I've tried the Array.reduce
technique suggested on another thread, but had problems syncing the ids and the requested data.
This is what I have so far. Does anyone have any suggestions?
aService.factory('dummy', function($http){
// Dummy resources.
var resources = [
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'
];
return {
data: function(callback){
var jquerySources = []
var promiseChain = $http({method: 'GET', url: resources[0]});
var l = resources.length
for (var i = 1; i < l; i++ ){
promiseChain.then(function(data){
jquerySources.push({
url: resources[i],
source: data
});
promise_chain = $http({method: 'GET', url: resources[i]});
if (i === l){
return callback(jquerySources);
}
});
}
}
}
});
Thankyou.
If you would need to do requests sequentially, you would create a promise which you could use as the head of your chain. Then, you could chain $http calls up to that head and resolve the head promise:
aService.factory('seq', function($http, $q){
// Dummy resources.
var resources = [
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'
];
var deferred = $q.defer();
var resourcePromise = deferred.promise;
var res = [];
angular.forEach(resources, function(resource){
return resourcePromise.then(function(){
return $http({ method: 'GET', url: resource });
}).then(function(data){
res.push({res: resource, data : data});
});
});
deferred.resolve();
return {
getResource: resourcePromise.then(function(){
return res;
})
};
});
but if requests would be in parallel - then it would be simplier solution. Just array of promises and simply call $q.all function for waiting to resolve all promises.
aService.factory('par', function($http, $q){
// Dummy resources.
var resources = [
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'
];
var promises = [];
var res = [];
angular.forEach(resources, function(resource){
promises.push(
$http({ method: 'GET', url: resource }).then(
function(data){
res.push({res: resource, data : data});
})
);
});
return {
getResource: $q.all(promises).then(function(){
return res;
})
};
});
Also note that in both cases we have res array for collecting results of requests.
EDIT: Plunker with example
You can indeed do this with reduce:
var chain = resources.reduce(function (sourcesPromise, url) {
return sourcesPromise.then(function (sources) {
return $http({method: 'GET', url: url})
.then(function (data) {
sources.push({url: url, source: data});
return sources;
});
});
}, $q.when([]));
chain.then(function (sources) {
// [{url, source}, ...]
});
based on How to chain a variable number of promises in Q, in order?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With