371273
371273

Reputation: 5446

Multiple promises from single $http request in AngularJS

I would like to implement promises in my AngularJS application like you can see in this example: https://stackoverflow.com/a/12360882/371273

My application will take multiple arrays of data making multiple database hits on my server, but I have configured my server to return all of that data as one response in the idea of minimizing requests to keep my application as efficient as possible (the data is essentially useless unless all of the data gets to the client). So instead of doing this...

MyCtrl.resolve = {
    projects : function($q, $http) {
        return $http.get('/api/projects'});
    },
    clients : function($q, $http) {
        return $http.get('/api/clients'});
    }
};

I would like to be able to make a single $http GET request to a URL like /api/allData, and then have a promise for projects that will be set equal to allData.projects and a promise for clients that will be set equal to allData.clients, etc. (where allData is the data that came back with my single request). I'm still very new to promises, can someone give me an example of how I would set up these promises inside MyCtrl.resolve?

Upvotes: 3

Views: 6170

Answers (2)

Denison Luz
Denison Luz

Reputation: 3565

I believe that's what you are looking for:

var myApp = angular.module('myApp', []);

myApp.factory('myService', function ($http, $q) {
    return {
        getAllData: function () {
            return $q.all([ 
                // $q will keep the list of promises in a array
                $http.get('/api/projects'),
                $http.get('/api/clients')
            ]).then(function (results) {
            // once all the promises are completed .then() will be executed 
            // and results will have the object that contains the data 
                var aggregatedData = [];
                angular.forEach(results, function (result) {
                    aggregatedData = aggregatedData.concat(result.data);
                });
                 return aggregatedData;
            });
        }
     };
 });

The you can get your data from the final aggregatedData array (e.g.:aggregatedData[0], aggregatedData[1],...)

You can set up these promises inside MyCtrl.resolve in a single call:

resolve = {
    getAllData : myService.getAllData()
}

Upvotes: 6

Caio Cunha
Caio Cunha

Reputation: 23394

Well, there is not much of a point in using two promises that you know represent the same promise. But you could indeed create a service that receive handles the one promise and return two. Something like this:

var mod = angular.module('mod', []);
mod.service('theService', function($q, $http) {
  return function() {
    var cliDeferred = $q.defer(),
        proDeferred = $q.defer();

    $http.doYourStuff().then(function _onSuccess(data) {
      cliDeferred.resolve(data.clients);
      proDeferred.resolve(data.projects);
    }, function _onError(err) {
      cliDeferred.reject(err);
      proDeferred.reject(err);
    });

    return {clients: cliDeffered.promise, projects: proDeferred.promise};
  };
});

But as I said, there is not much of a point in this. Maybe a better solution, considering your service will return an array, would be return an object with empty arrays and fill them when the $http promise gets completed.

Upvotes: 4

Related Questions