AngularJS - When does a service retrieve data?

When does a Service / Factory retrieve data from an HTTP request?

When a factory is created in a service, I am curious as to when the HTTP request is sent, and how it is processed after the app is running for some time.

I'm writing my code using Ionic Framework. Once I initialize my app, and it stays open for a day or two, will the JSON data be refreshed at any interval? Or does it only refresh the data once the app is closed, and opened once again?

My requirement for the HTTP request, is that it is updated every day at the 00:01 AM.

I suppose my general question is: how does an HTTP request fetch data? And How does a service work in AngularJS.

Here is my code to retrieve a JSON package:

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

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

   return {
     all : function() {
       return $http({
         url: 'http://middmenuapi.herokuapp.com/',
         method: 'GET'
       })
     }
   }
});

Calls to $http() (or any of the aliases, such as $http.get() etc) invoke a web request immediately (barring any manipulation by inspectors or third-party components). It is analogous to issuing an XmlHttpRequest or JSONP request in other frameworks, like jQuery.

Services are created as singletons, so they are created once when they are first requested, and the same instance is injected from that point on. What the service does is entirely up to you, as Angular only deals with instantiating it, resolving any of its dependencies, and injecting it anywhere it's requested.

If you have an application that is running for long periods of time and needs to be updated with data, you'll need to architect it appropriately. Obviously I don't know the full requirements or particulars of your spec, but I can give you some hints to maybe get you going.

High level, it sounds like you need a function to operate on a timer (using the $timeout service), and if you meet or exceed a time window, invoke an $http request to retrieve the latest data and route it along to various components that need it. Then, it should mark the time frame it should next operate, then set a timeout again so it can wake further down the road and see if it's time to do work again.

The first thing to think about is where should this functionality live? If you only need it to happen in a certain controller, then you can do it all there in that controller using $timeout and $http. On the other hand, if you need to reuse this data in multiple places, you'll want to use a service. If you use a service, which is likely, then you need to figure out the best way to get those changes to the various parts of your app that need it.

My recommendation is to use Angular events on the $rootScope to $broadcast from your service when your $http request has updated data. Then, your various controllers, services, and directives that consume this data can subscribe to this event using $scope.$on and react appropriately. This keeps the service decoupled from the things that use it and allow them to react to changes easily.

All the service does is set a timeout, when it lapses check for data, if it has data, broadcast the data in an event on $rootScope, and set another timeout. The clients just listens and updates its local scope with the new data when it receives the event from the service.

This plunk contains a silly example. You'd want to change it to schedule work at a time of day or whatever you see fit, and then also have it make an $http request rather than send the current date.

angular.module("demo", [])
  .service('myService', ['$rootScope', '$timeout', '$http', function($rootScope, $timeout, $http) {
      var state = { timeout: null, next: null };

      function work() {
        var now = Date.now();

        if (now >= state.next) { // you can replace with your own logic to schedule when it should occur (like a specific time of day). in this example, we poll every second, but do work every 5.

          // this is where your $http service can do work, something like $http.get(...).success(function(data) { $rootScope.$broadcast('myService.data', data); });
          $rootScope.$broadcast('myService.data', new Date());
          state.next = now + 5000; // do work every five seconds
        }

        state.timeout = $timeout(work, 1000); // poll every second
      }

      return {
        start: function() {
          if (state.timeout) $timeout.cancel(state.timeout); // cancel pending timeout
          work(); // first time will just schedule work to be done in the future
        },
        stop: function() {
          if (state.timeout) $timeout.cancel(state.timeout); // cancel pending timeout
        }
      };
    }])
  .controller('DemoCtrl', ['$scope', function($scope) {
      $scope.title = "Hello, World";

      // here, the controller subscribes to the event, and when it occurs, it copies the event data to a local scope item
      $scope.$on('myService.data', function(evt, data) {
        $scope.$apply(function() {
          $scope.myServiceData = data;
        });
      });
    }])
    .run(['myService', function(myService) {
      myService.start(); // starts the service when the app runs
    }]);