Angular $ q returns multiple $ http calls

I am working on a call to $ http, which iterates over each of several api and returns all the data in one object. I usually have a promise ready to be resolved when a call to $ http was received. Similar to this:

function getAllData(api) { return $http({ method: 'GET', url: '/api/' + api }) .then(sendResponseData) .catch (sendGetVolunteerError); } 

The current function I have loops over each api and pushes each object in the api into an array, and then pushes it into a shared array. I had this functioning, returning a multidimensional array that needed to be smoothed out.

I would like to return this as a promise, but return undefined . Here is what I still have? Is there a better way to approach this?

DATASERVICE:

 function getSearchData() { return { loadDataFromUrls: function () { var apiList = ["abo", "ser", "vol", "con", "giv", "blo", "par"]; var deferred = $q.defer(); var log = []; angular.forEach(apiList, function (item, key) { var logNew = []; $http({ method: 'GET', url: '/api/' + item }).then(function (response) { angular.forEach(response.data, function (item, key) { this.push(item); }, logNew); return logNew; }); this.push(logNew); }, log); $q.all(log).then( function (results) { deferred.resolve( JSON.stringify(results)) }, function (errors) { deferred.reject(errors); }, function (updates) { deferred.update(updates); }); return deferred.promise; } }; }; 

Controller:

 function getSearchData(){ return dataService.getSearchData.loadDataFromUrls; } $scope.searchData = getSearchData(); 
+6
source share
3 answers

$q.all and the map function is what you need:

 function getSearchData() { return { // returns a promise for an object like: // { abo: resultFromAbo, ser: resultFromSer, ... } loadDataFromUrls: function () { var apiList = ["abo", "ser", "vol", "con", "giv", "blo", "par"]; return $q.all(apiList.map(function (item) { return $http({ method: 'GET', url: '/api/' + item }); })) .then(function (results) { var resultObj = {}; results.forEach(function (val, i) { resultObj[apiList[i]] = val.data; }); return resultObj; }); } }; } 
+16
source

If you have an arbitrary set of api calls, I would do something like this:

 function getSearchData(){ var deferred = $q.defer(); var noOfCalls = apiList.length; var results = []; var called = 0; angular.forEach(apiList, function(item, key) { $http.get(url).then(function(result){ results.push(result); called++; if(called == noOfCalls){ deferred.resolve(results); } }) }); return deferred.promise; } 

However, if you know that every api call best uses $ .all this way

 function search1(){ return $http.get(search1Url).then(function(result){ // do something to it return result; }); } function search2(){ return $http.get(search2Url).then(function(result){ // do something to it return result; }); } function search3(){ return $http.get(search3Url).then(function(result){ // do something to it return result; }); } function search4(){ return $http.get(search4Url).then(function(result){ // do something to it return result; }); } function getSearchResult(){ return $q.all([search1(), search2(), search3(), search4()]).then(function(results){ // OPTIONAL aggregate results before resolving return results; }); } 
+1
source

You should add a promises list in $q (not allowed promises as in your code), which is $promise service

Example:

 var firstPromise = service1.getMethod1().$promise; var secondPromise = service2.getMethod2().$promise; $q.all([firstPromise, secondPromise]).then(function(dataList){ // dataList[0] will be result of `firstPromise` // dataList[1] will be result of `secondPromise` }); 
0
source

Source: https://habr.com/ru/post/984048/


All Articles