Search code examples
javascriptangularjsangularjs-serviceangularjs-http

Why use Angular Service to gather information, instead of just $http?


Two options, which is better and why:

Example A.

  1. app module
  2. service containing model data
  3. controller to call in data from service

File 1: Users.js:

      angular.module('users', []);

File 2: userService.js:

angular.module('users').service('userService', ['$q', UserService]);

  function UserService($q) {
    var users = [
      {
        name: 'Bob Smith',
        age: 26,
        address: 'London',
      },
      {
        name: 'John Simpson',
        age: 41,
        address: 'New York',
      },
      {
        name: 'Maria West',
        age: 36,
        address: 'Chicago',
      }
    ];

    // Promise-based API
    return {
      loadAllUsers : function() {
        // Simulate async nature of real remote calls
        return $q.when(users);
      }
    };
  }

})();

File 3: UserController.js:

          angular.module('users').controller('UserController', ['$scope', function($scope) {

        $scope.selected     = null;
        $scope.users        = [];
        $scope.selectUser   = selectUser;
        $scope.toggleList   = toggleUsersList;
        $scope.makeContact  = makeContact;

        userService
          .loadAllUsers()
          .then( function( users ) {
            $scope.users    = [].concat(users);
            $scope.selected = users[0];
          });
}]);

Example B:

  1. app module, and controller drawing model data from from .json file through $http service.
  2. json file to hold model data.

File 1: Users.js:

      angular.module('users', []);

         .controller('userController', [
            '$scope', 
            '$http', 
            function($scope, $http, $routeParams) {

            $http.get('data.json').success(function(data) {
            $scope.userData = data; 
            });

         }]);

File 2: userService.json

         [
          {
            'name': 'Bob Smith',
            'age': 26,
            'address': 'London',
          },
          {
            'name': 'John Simpson',
            'age': 41,
            'address': 'New York',
          },
          {
            'name': 'Maria West',
            'age': 36,
            'address': 'Chicago',
          }
        ];

B seems more logical (and easier to me), but I've seen people do A. I presume there's an advantage - can anyone explain it?


Solution

  • Yes, A looks preferred approach, because it looks kind of following separation of concern, and following Single Responsibility Principle.

    Service

    • Which is responsible for getting data from back-end
    • Exposed various method to other component to retrieve data from single place.

    Controller

    • Communicate between services and the views
    • Also it handles other view specific business logic.

    Why Approach B is bad?

    You have simple ajax call inside a controller itself. Ya that's look really nice.

    But suppose you wanted to have userData to be displayed on two other page, then what will you do? I know you are going to replicate same code inside other controller too. And here the problem comes in to picture. Same thing is going to get repeat for multiple times for no reason. Correct? So replicating code on multiple places will add Code Maintainability problem in future. That's the reason, you shouldn't go for first approach.

    Where as go for approach A would have better maintainable & structured code.

    Edit

    Inside your approach A you shouldn't be hard code all the data. It should retrieve from server either by calling server API method or call to .json file. Also I'm going to write down correct service code approach A, you could see after this explanation end. By looking at refactored code, you can see now we had get rid of $q service. Because you don't need to worry about custom promise implementation, as $http methods does return promise, by using which code can follow promise chain pattern by take use of .then

    angular.module('users').service('userService', ['$http', UserService]);
      function UserService($http) {
        return {
          loadAllUsers : function() {
            // Simulate async nature of real remote calls
            return $http.get('users.json'); //return promise from herer
          }
        };
      }
    })();