2

I have two url endpoints say: "fruitInfo" and "fruitDetails"

I want to return an object that contains:

var fruitInfoDetails = {"fruitInfo": <contents of fruitInfo response data>,
"fruitDetails": <contents of fruitDetails response data>}

Inside a service I call:

var fruitInfoDetails = {};
this.getFruitInfo()
.then(function(data) {

   fruitInfoDetails['fruitInfo'] = data;
   this.getFruitDetails(data.nameOfFruit).then(function(data) {
        fruitInfoDetails['fruitDetails'] = data;      
   })
});

Assume the this.getFruitInfo() and this.getFruitDetauls() contains functions that return the $http promise going to each of those endpoints.

What is the proper/elegant way to do this? If there is a function that I could pass a list of fruits "[Apple, Pear, Orange]", and it could return me a list of fruitInfoDetails objects, that would be perfect.

1 Answer 1

6

You can make your own promise using the $q service, and resolve it when the 2nd call completes.

angular.module('mymodule').factory('FruitService', function($http, $q) {
return {
    getFruitInfoDetails: function() {
        // make our own promise
        var deferred = $q.defer();
        // 1st call
        $http.get("fruitInfo").then(function(fruitInfo) {
            // 2nd call
            $http.get("fruitDetails").then(function(fruitDetails) {

                deferred.resolve({
                    fruitInfo: fruitInfo,
                    fruitDetails:fruitDetails
                });
            });
        });
        return deferred.promise;
    }
};
});

You can also use $q.all() in order to wait for both requests to finish before resolving. It result in less indentation.

angular.module('mymodule').factory('FruitService', function($http, $q) {
return {
    getFruitInfoDetails: function() {
        // make our own promise
        var deferred = $q.defer();
        // 1st call
        var infoPromise = $http.get("fruitInfo");
        var detailsPromise = $http.get("fruitDetails");

        $q.all([infoPromise, detailsPromise]).then(function(data) {
            deferred.resolve({
                fruitInfo: data[0],
                fruitDetails: data[1]
            })
        });

        return deferred.promise;
    }
};
});

The requested retrieving a list of given fruits:

angular.module('mymodule').factory('FruitService', function($http, $q) {

return {
    getFruitInfoDetails: function(fruit) {
        // make our own promise
        var deferred = $q.defer();

        // we'll asume that you can put the fruit as part of the path
        var infoPromise = $http.get("fruitInfo/" + fruit);
        var detailsPromise = $http.get("fruitDetails/" + fruit );

        $q.all([infoPromise, detailsPromise]).then(function(data) {
            deferred.resolve({
                fruitInfo: data[0],
                fruitDetails: data[1]
            })
        });

        return deferred.promise;
    },

    getFruitList: function(fruits) {
        var deferred = $q.defer();

        // map our list of fruits to a list of the promises of fruit info
        var allPromises = fruits.map(function (fruit) {
            return this.getFruitInfoDetails(fruit);
        });

        // wait for all the fruits to be resolved then just resolve our own promise
        $q.all(allPromises).then(function(allTheFruitInfoDetails) {
            deferred.resolve(allTheFruitInfoDetails);
        });
        return deferred.promise;
    }
};
});
Sign up to request clarification or add additional context in comments.

7 Comments

Nice use of $q.all!
thank you, it does help make it easier to understand, and it allows for both requests to be done in parallel. :)
Could you show an example of a function in which someone were to pass a list of fruitNames in a list, and an array of "fruitInfoObjects" is to be returned?
@Rolando I edited the response to include that. Uhm, you might have to scope the getFruitInfoDetails call. but that's what you should be looking for. promise hell. :)
If promise hell is what I am looking for, you must be satan... your a master of them. Upvoted.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.