Javascript Angular: how to tie an unknown number of promises

I am writing an Angular.js service to pull out several JSON feeds. Initially, the service does not know how many / how many resources are required for the request; they depend on the identifiers returned by another request.

I have a headache linking $http service requests together. Is there a commonly used pattern?

I tried the Array.reduce method proposed in another thread, but had problems synchronizing identifiers and requested data.

This is what I still have. 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.

+7
javascript promise asynchronous
source share
2 answers

If you would need to fulfill the requests sequentially , you would create a promise that you could use as the head of your chain. You can then associate the $ http calls with this head and resolve the chapter 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 the requests are in parallel , then this will be a simpler solution. Just an array of promises and just call the $ q.all function to wait for all promises to resolve.

 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 a res array to collect query results.

EDIT: Plunker with an Example

+6
source share

You can really do it 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 How to link a variable number of promises in Q, in order?

+2
source share

All Articles