Question

I have a factory which returns an object with several properties. But each property value is computed by ajax call and in some cases I do promise chaining in order to set a property value. Before I return the object how do i make sure all ajax calls are done such that property values are assigned

My factory looks something like this

app.factory('Resource', ['$http', '$q', function ($http, $q) {
    var Resource = {
    masterDB: null,
    replicaDB: null,
    replicaCluster: null,
    masterForests: null,
    forestHosts:{}
};

    Resource.setMasterDB = function (dbname) {
        console.log('inside setMasterDB', dbname);
        this.masterDB = dbname;
    };


    Resource.getResources = function (dbname) {
        var  url = '/manage/v2/databases/'+ dbname + '?format=json';
        $http.get(url).then(function (response) {
            Resource.masterForests = getAttachedForests(response.data);
            console.warn('Master Forests = ', Resource.masterForests);
            return response;
        }).then(function (response) {
            Resource.replicaCluster = getReplicaClusters(response.data);
            console.warn('Replica Cluster = ',Resource.replicaCluster);
        }).then(function () {
            console.log('final then',  Resource.masterForests);
            var reqs = function () {
                var arr = [];
                angular.forEach(Resource.masterForests, function(forestName){
                    arr.push($http.get('/manage/v2/forests/'+ forestName + '?format=json'));
                });
                return arr;
            }.call();

                console.log('reqs = ', reqs);

            $q.all(reqs).then(function (results) {
                console.warn(results);
                angular.forEach(results, function(result){
                    console.log('HOST', getForestHost(result.data));
                });
                return results;
            });
        });

    };
    console.warn('RESOURCES: ', JSON.stringify(Resource));
    return Resource;

}]);
Was it helpful?

Solution 2

Here's the working code

 getResources: function (dbname) {
            var  url = '/manage/v2/databases/'+ dbname + '?format=json';
            return $http.get(url).then(function (response) {
                Resource.masterForests = getAttachedForests(response.data);
                Resource.appservers = getAttachedAppServers(response.data);
                Resource.replicaClusters = getReplicaClusters(response.data);
                console.warn('Master Forests = ', Resource.masterForests);
                return Resource.replicaClusters;
            }).then(function(replicaClusters) {
                var clusterArr = [];
                angular.forEach(replicaClusters, function(cluster) {
                    clusterArr.push($http.get('/manage/v2/clusters/'+ cluster + '?format=json'));
                });
                return $q.all(clusterArr).then(function(results) {
                    angular.forEach(results, function(result) {
                        var cluster = result.data['foreign-cluster-default'].name;
                        var dbs = getReplicaDBs(result.data);
                        Resource.replicaDBs[cluster] = dbs; 
                    });
                });
            }).then(function() {
                var forestarr = [];
                    angular.forEach(Resource.masterForests, function(forestName){
                        forestarr.push($http.get('/manage/v2/forests/'+ forestName + '?format=json'));
                    });     
                return $q.all(forestarr).then(function (results) {
                    angular.forEach(results, function(result){
                        var host = getForestHost(result.data);
                        var forest = result.data['forest-default'].name;
                        Resource.forestHosts.push(host);
                        // group forest by hosts
                        groupForestsByHost(Resource, host, forest); 
                    });
                });
            });
        }

In controller

Resource.getResources($scope.db).then(function() {
     $scope.masterForests = Resource.masterForests;
     $scope.replicaClusters = Resource.replicaClusters;
     $scope.forestHosts = Resource.forestHosts;
     $scope.forestsOnHosts = Resource.forestsOnHosts;
     $scope.replicaDBs = Resource.replicaDBs;
     $scope.appservers = Resource.appservers;
 }

OTHER TIPS

We had scenario where the datas have to be updated from two different ajax responses, we have followed the below approach.

For Example:

function functionname()
{

var First_Response = $http.$get("/test1/test2/...");
var Second_Response = $http.$get("test3/test4/...");
return $q.all([First_Response,Second_Response]); // This function will return only when all the ajax responses are obtained.
}

In the below url: https://docs.angularjs.org/api/ng/service/$q

It is mentioned that $q.all will return result only when all the requests mentioned in the array gets the ajax response. We tried this approach and it worked for us. Hopefully it will give some pointers

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top