3

I have an angular factory that makes an $http call with a get and then.

 .factory('DataModel', function($http) {

I have a .get.then that works great. The value comes back, and since I originally returned a function to return the factory value, everything updates when it changes.

Now I have to make a dependent call based on the data that returned the first time.

First try: $http.get.then inside the outer $http.get.then.

The inner (dependent) call successfully gets the data, but when it updates the factory parameters only the first .get.then is picked up by the calling controller.

Next try: $scope.$watch.

angular.module('starter.services', [])
 .factory('DataModel', function($scope, $http) {

If I put a $scope parameter in there I get an error:

Unknown provider: $scopeProvider <- $scope <- DataModel

So I can't seem to use the $scope.$watch method.

Third try: callbacks?

I'm afraid that if I use a callback approach I'll get the data back, but it won't update just like my nested get.then. didn't update.

Here is my full factory:

angular.module('starter.services', [])

.factory('DataModel', function($http) {

    var days = {};
    var todaysFlavorIndex = 32;
    var todaysFlavorName = [32, 'Loading ...', "vanilla_chocolate_chip.jpg"];
    var daysLeftCalendar = [];

    var flavors = [];

    // calendar objects
    $http.get("https://jsonblob.com/api/5544b8667856ef9baaac1")
        .then(function(response) {
            var result = response.data;
            days = result.Days;

            var dateObj = new Date();
            var day = dateObj.getDate();

            var endOfMonthDate = new Date(new Date().getFullYear(), dateObj.getMonth(), 0).getDate();
            for (var di = day; di <= endOfMonthDate; di++) {
                var flavor = days[di - 1];
                daysLeftCalendar.push(flavor[1]);
            }

            var todaysFlavorIndex = -1;
            // $scope.$watch('todaysFlavorIndex', function() {
            //    // Http request goes here
            //    alert('updating !');
            // });
            for (var i = 0; i < days.length; i++) {
                if ((days[i])[0] == day) {
                    todaysFlavorIndex = (days[i])[1];
                }
            }

            // flavors
            $http.get("https://jsonblob.com/api/55450c5658d3aef9baac1a")
                .then(function(resp) {
                    flavors = resp.data.flavors;
                    todaysFlavorName = flavors[todaysFlavorIndex];
                });
        }); // end then

    return {
        getDays: function() {
            return days;
        },
        getMonth: function() {
            return days;
        },
        getFlavors: function() {
            return flavors;
        },
        getTodaysFlavorIndex: function() {
            return todaysFlavorIndex;
        },
        getTodaysFlavorName: function() {
            return todaysFlavorName; // flavors[todaysFlavorIndex];
        },
        today: function() {
            var dateObj = new Date();
            var day = dateObj.getUTCDate();
            return todaysFlavorIndex;
        },
        remainingFlavorIndexes: function() {
            return daysLeftCalendar
        }
    };
})
1

1 Answer 1

9

Firstly , services has no $scope.

So injecting scope in factory will always throw you exceptions.

Secondly , try to catch callback from controller instead of factory

Try like this

angular.module('starter.services', [])

.factory('DataModel', function($http) {

    return {

        myFunction: function() {
            return $http.get("https://jsonblob.com/api/5544b8667856ef9baaac1");
        }

    }

})

.controller("myCtrl", function($scope, DataModel) {

    DataModel.myFunction().then(function(result) {
        // success 
        // put your code here
    }, function(e) {
        // error
    });

})

Thirdly, If you wanna have inner $http you can use $q

Try like this

angular.module('starter.services', [])

.factory('DataModel', function($http) {

    return {

        myFunction: function() {
            return $http.get("https://jsonblob.com/api/5544b8667856ef9baaac1");
        },
        myFunction2: function() {
            return $http.get("https://jsonblob.com/api/55450c5658d3aef9baac1a");
        }

    }

})

.controller("myCtrl", function($scope, DataModel, $q) {

    $q.all([
        DataModel.myFunction(),
        DataModel.myFunction2()
    ]).then(function(data) {
        console.log(data[0]); // data from myFunction
        console.log(data[1]); // data from myFunction2
    });

});
Sign up to request clarification or add additional context in comments.

4 Comments

The 'no $scope in services' helps a lot. Thanks for showing me two ways to tackle this. When I try doing the then() from the controller I get: "TypeError: DataModel.getDays(...).then is not a function" ... but you can see from my code (above) it is a function.
@micahhoover can you put it on plunkr or jsfiddle and provide a link for me ?
Since it's rolled in with Ionic, you might not be able to easily reproduce, but here it is: jsfiddle.net/hcjfm22m
DataModel.getDays() has no callbacks. then only work in callback

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.