javascript - $q, $http and parallel processing of results -


i using angular's $q execute multiple $http post calls asynchronously. working nicely , calls returning @ same time, within few milliseconds.

the problem next step process results. want results processed in parallel seem queuing , process 1 @ time.

i've pasted code below , appreciate if can point me in right direction how ensure results processed in parallel. code searchservice , 'search' method entry point controller.

var searchservice = {     searchoptions: {},     searchresults: {         foos: [],         bars: [],         typebs: [],         typeas: []     },     searchfacets: {         foos: [],         bars: [],         typebs: [],         typeas: []     },     processresults: function (object, start) {         return function (response) {              //var marker = +new date();  // log end timestamp             //var diff = marker - start;             //console.log("start processing " + object.name + ": " + diff);              ...cut brevity...              //marker = +new date();  // log end timestamp             //diff = marker - start;             //console.log("finished processing " + object.name + ": " + diff);         }     },     getsinglesearchparams: function (object) {         return {             searchphrase: this.searchoptions.searchphrase,             type: object.typeid,             facets: object.facets         };     },     getsearchresults: function (object, start) {         if (object.include)             datafactory.searchfactory.search(this.getsinglesearchparams(object)).success((this.processresults)(object, start));         else {             var message = object.name + " not selected search";             throw message;         }     },     search: function () {         var start = +new date();         var searches = {};         if (this.searchoptions.foos.include) {             searches.fooresults = this.getsearchresults(this.searchoptions.foos, start);         }         if (this.searchoptions.bars.include) {             searches.barresults = this.getsearchresults(this.searchoptions.bars, start);         }         if (this.searchoptions.typebs.include) {             searches.typebresults = this.getsearchresults(this.searchoptions.typebs, start);         }         if (this.searchoptions.typeas.include) {             searches.typearesults = this.getsearchresults(this.searchoptions.typeas, start);         }         $q.all(searches);     } }; 

searchfactory's 'search' method contains $http calls:

searchfactory.search = function (searchoptions) {     return $http.post(searchurl, searchoptions); }; 

the commented out code shows timings , revealed serial nature of processing results...

start processing typebs: 162 finished processing typebs: 164 start processing typeas: 535 finished processing typeas: 535 start processing foos: 553 finished processing foos: 554 start processing bars: 1616 finished processing bars: 1617 

your http requests are running in parallel. processresults function executed after http requests have returned, why appear serial you. add log line here , see happens:

getsearchresults: function (object, start) {     if (object.include)         console.log("starting request object %o", object);          // http request made         datafactory.searchfactory.search(this.getsinglesearchparams(object)).success((this.processresults)(object, start));     else {         var message = object.name + " not selected search";         throw message;     } }, 

by way, $q.all doesn't in code. benefit of $q.all allows after guaranteeing of promises have resolved. however, you're processing each request returns.

var promises = [   $http.get('foo'),    $http.get('bar') ];  // @ point, both http requests have fired, in parallel. $q.all isn't responsible this.  $q.all(promises) .then(function(responses){   // if execute logic can happen after both http requests return, you'd use $q.all. }); 

if want process search results after searches have finished, place processing business logic inside callback $q.all.

edit: refactored code little bit uses $q.all.

var searchservice = {   processresults: function(responses) {     // responses array of response objects. whatever here.   },   getsinglesearchparams: function(object) {     return {       searchphrase: this.searchoptions.searchphrase,       type: object.typeid,       facets: object.facets     };   },   getsearchresults: function(object, start) {     // no need throw error here. place call method, can guarantee called object selected search.     // i've added `return` keyword, returns promise, , removed `processresults`. process reults after `$q.all`.     return datafactory.searchfactory.search(this.getsinglesearchparams(object));   },   search: function() {     var self = this;     var start = new date();     var promises = ['foos', 'bars', 'typebs', 'typeas'].reduce(function(promises, search) {       if (self.searchoptions[search].include) {         promises.push(self.getsearchresults(self.searchoptions[search], start))       }       return promises;     }, []);     return $q.all(promises)     .then(this.processresults.bind(this));   } }; 

Comments