Search code examples
javascriptangularjshttppolling

AngularJS - polling into persistent data store


Angular noob here. I'm building an app that needs to poll a url every second, and store that data persistently, as it needs to be accessed by multiple views/controllers.

What I've done to handle this is put my http request into a factory, and the data is made available to controllers through functions in the factory. The issue I'm having now is that the factory function is envoked before the http request, causing errors in my app.

Here is the code:

App.factory('metrics', function($http){
    var service;
    var users = [{laps:[]}];
    var updateMetrics = function(){
        //updates the users array in the factory
    };
    $http.get('data.csv').success(function(data) {
        var temp_array = data.split(" ");
        updateMetrics(0, temp_array);
    });

    service.lastLapInfo = function(){
        var lastlap = [];
        for (var i=0; i<users.length;i++)
        {
            var lap = users[i].laps[users[i].laps.length-1];
            lastlap.push(lap);
        }
        return lastlap;
    };
    return service;
});

App.controller('mainController', function($scope, $http, metrics) {
    $scope.users=metrics.lastLapInfo();
});

lastLapInfo() is getting called before the http request which is causing errors as there is no data in the array. Any thoughts?

Additionally - if I'm generally going about the wrong way to meet my use case (e.g. I should be using something else instead of a Factory) let me know!


Solution

  • This is a typical use case of a promise, or the angular's $q service.

    The following approach, uses a factory that returns a promise:

    App.factory('metrics', function($http){
       var service;
       ...
       service.load = function () {
          return $http.get('data.csv');
       });
       return service;
    });       
    

    In the controller you then call your metrics service, and you make use of the promise:

    App.controller('mainController', function($scope, $http, metrics) {
        metrics.load().then(function(response) {
           // at this point you know for sure that the request has terminated
           // you can call the service again to run lastLapInfo or do the logic in here.
        });
    });