0

I'm having trouble returning data from an Angular promise in a factory back to the controller. In this example,

http://jsfiddle.net/c3xjE/

update: function (staffList) {
    // get local last updated timestamp
    var lastUpdatedLocal = "";
    var lastUpdatedRemote = "";
    for (i=0; i < staffList.length; i++) {
        // get largest (most recent) timestamp
        if(staffList[i].entry_date > lastUpdatedLocal) {
            lastUpdatedLocal = staffList[i].entry_date;
        }
    }

// get remote last updated timestamp
var promise = $http.get('REMOTE_API_CALL')
    .success(function(data, status, header, config) {
        return lastUpdatedRemote = data[0].entry_date;
    }).then(function(response) {
        return response.data[0].entry_date;
        });
    console.log(promise);
}

I want to filter local data to get a local timestamp, compare it against a remote timestamp and instruct the controller to re-download all data if the local timestamp is less than the remote timestamp.

I'm filtering the local data okay and getting the expected result. Where I seem to get stuck is with promises. I can log out the filtered remote data within the .success or .then methods but haven't had much luck returning the values out of the promises. I know there's probably an issue with variable scope here.

Also, am I best to return a boolean from my factory to my controller (should I update? true/false) or perhaps a small obj with the local & remote timestamped data and leave the controller decide what to do from there?

Thanks in advance.

2
  • Couple of questions. Can we see your scope/view? Are you using an ng-repeat for the staffList? If so, and if you're going to the server to get the response anyhow, then could you just update the staffList with the response? Typically I just update whatever variable my ng-repeat is bound to and then let angular do the dirty checking to see if an update of the dom is needed. Is this being triggered by the user via a refresh action or is this running in the background? Commented Jul 11, 2014 at 16:37
  • I have since refactored all of this so I don't have an example of the controller as it was. At the time I was hoping for the service to return an object with the timestamps or even simply return true/false and the controller would have handled the boolean response. I'm using Ionic's collection-repeat for performance. The user "pulls-to-refresh" and this is why I'm checking the timestamps instead of downloading all of the data and reassigning it to the scope. There's no point doing that if there's no change in the data. I had no choice but to return the promise to the controller in the end. Commented Jul 11, 2014 at 16:43

1 Answer 1

2

Here is the best example I have of how to implement this. I assumed some stuff about your controller and factory. Note that you need to inject $q into your factory to use deferreds. This is how I do it in my app.

http://jsfiddle.net/JimTheDev/2zLEp/

/*
  NOTE: make sure to inject $q into your factory before
  this. For the purposes of my example, let's assume your
  factory looks like this:
*/
app.factory('mySweetFactory', ['$q', function($q) {
    return {

        // You probably have a bunch of other methods like
        // this one in your factory.
        myothermethod: function(argument1, argument2) { 
            /* some code here */
        },

        update: function (staffList) {

            // Create a new deferred object
            var deferred = $q.defer();

            // get local last updated timestamp
            var lastUpdatedLocal = "";
            for (i=0; i < staffList.length; i++) {
                // get largest (most recent) timestamp
                if(staffList[i].entry_date > lastUpdatedLocal) {
                    lastUpdatedLocal = staffList[i].entry_date;
                }
            }

            // Make a call to the remote api
            $http.get('REMOTE_API_CALL').then(function(response) {

                // Get the remote last updated
                // time from the response
                var lastUpdatedRemote = response.data[0].entry_date;

                // Check if local or remote is larger
                // You probably need to modify this 
                // depending on your datetime formatting. 
                // I am assuming an epoch string.
                if(lastUpdatedRemote > lastUpdatedLocal)
                {
                    // Resolve the deferred and return
                    // the data so that the controller can
                    // use it to update the view
                    deferred.resolve(response.data);
                } else {
                    // Since we don't need to do anything,
                    // reject the deferred
                    deferred.reject();
            });

            // Return the promise from the deferred object
            // immediately. We will eventually either 
            // resolve or reject it, but at the start, it
            // will be in a pending state.
            return deferred.promise;
        }
    };
}]);

app.controller('mySweetController', ['mySweetFactory', function(mySweetFactory){
    $scope.doUpdate = function() {
        mySweetFactory.update($scope.staffList).then(function(newStaffList) {
            // Promise was resolved. List needs updating!
            $scope.staffList = newStaffList;
        }, function(){
            // Promise was rejected. No update needed!
        });
    };
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

My pleasure. Glad it was useful.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.