Ionic:Hybrid Mobile App Development
上QQ阅读APP看书,第一时间看更新

Ionic services vs factories

Services/factories in Ionic are used to abstract common business logic and integration to the backend services. A data access layer and business logic layer can be implemented using Ionic service or factory. Ionic service or factory can be used interchangeably and are available as a method on the angular.module object.

Note

Generally, a service is used to represent the data access layer whereas a factory is used to implement the entity layer or business logic layer. Both objects are singleton in nature, meaning only once instance is created throughout the app's life cycle, which is shared between multiple controllers or other angular modules.

We will take the example of our BookStore App to create an authentication service for it, and a booksFactory with factory object.

Ionic service – authentication service

Ionic service is a special Angular construct that represents an object created using a constructor pattern, exposing certain methods abstracting app logic or integrating with the backend. Services can be injected into any module using Dependency Injection (DI) but its instance is created only once. Service is lazily instantiated only when any component that depends on it comes into focus. There are multiple in-built utility services such as $http, $timeout, and so on which can be used throughout the app.

A service is created using the .service() method available on the angular.module object. The first argument needs to be the name of the service and the second argument is the dependency injection array, which has the names of all dependencies, and the last element is the constructor function.

The following code explains the usage of this service:

angular.module('module.services',[])
.service('ServiceName',
  ['dependency1','dependency2',
    function(dependency1,dependency2) {
      this.variable1 = 1 //default value
      this.variable2 = 3 //default value
      this.method1 = function() {
        return binaryOp(this.variable1,this.variable2);
        //binaryOp can be any local method
      }
    }
  ]
);

We can model our BookStore sample app's authentication service using this construct. We will expose four given methods to this service as follows:

  • signup: A method used to sign up a new user, taking input as a user object
  • login: A method to log in a user and save sessionToken to cookies
  • logout: A method to log a user out of a web service and remove the sessionToken argument

Here is the code sample for defining a service:

angular.module('BookStore.Services',[])
.service('UserAuth',
  ['$http','$cookies',
    function($http,$cookies) {
      this.baseApiUrl = 'http://localhost:9000/api'; // Sample URL to be replaced by your own API url
      this.signup = function(userObj) {
        // Making a POST $http call to /signup API call
        return $http.post(this.baseApiUrl+'/signup',userObj)
      }
      this.login = function(username,password) {
        // Making a GET $http call to /login API call
        return $http.get(this.baseApiUrl+'/login?username='+username+'&password='+password)
        .then(function(response) {
          if(response.data.loginSuccessful == 'true')
          {
            $cookies.put('sessionToken',response.data.sessionToken);
          }
        });
    }
    this.logout = function() {
      // Making a GET $http call to /logout API call
      return $http.post(this.baseApiUrl+'/logout?sessionToken='+$cookies.get('sessionToken'))
      .then(function(response){
        $cookies.remove('sessionToken');
      });
    }
  }
]);

Ionic factory – BooksFactory

Ionic Factory is very similar to service and can be used interchangeably with it. The only syntactical difference is that it returns an object exposing selective methods, which can be called to use the service. It is also based on a singleton pattern and the same instance is shared between different modules.

The service or factory can be used by injecting it into any controller or other service, and calling the exposed methods passing required parameters. We can use this to create a factory pattern for our app using it to manage entities or objects.

The following code explains the usage of this service:

angular.module('module.services',[])
.factory('ObjectFactory',
  ['dependency1','dependency2',
    function(dependency1,dependency2) {
      this.objectsArray = [] //load array from server
      this.getObjects = function() {
        return this.objectsArray;
      }
    }
  ]
);
.controller('ConsumerCtrl',['ObjectFactory',function(ObjectFactory) {
  $scope.objects = ObjectFactory.getObjects();
}]);

We can create a BooksFactory factory to implement logic regarding managing book entities in our app. We can expose the methods that can be used by multiple views or controllers. We will be exposing the following methods:

  • getBooks: A method that can be used to get a list of books to be displayed. Certain optional arguments can be passed to the method to filter the results:
    • Category: Fetch books related to that category
    • Author: Fetch books for a specific author
    • SortBy: Pass the field according to which list should be sorted
  • getBookDetails: Passing a specific book ID to get all the details regarding that book.
  • addToFavorite: Adding a book to your favorites.

Here is the code sample for defining a service:

angular.module('BookStore.Services',[])
.factory('BooksFactory',
  ['$http',
    function($http) {
      var baseApiUrl = 'http://localhost:9000/api'; // Sample URL to be replaced by your own API url
      var booksList = [];
      var favoriteBooks = [];
      var getBooks = function(category,author,sortBy) {
        var filters = {};
        if(category)
          filters['category'] = category;
        if(author)
          filters['author'] = author;
        if(category)
          filters['sortBy'] = sortBy;
        // Making a POST $http call to /signup API call
        return $http.post(baseApiUrl+'/books',filters)
      }
      var getBookDetails = function(bookId) {
        // Making a GET $http call to /books/:id API call
        return $http.get(baseApiUrl+'/books/'+bookId);
      }
      var addToFavorite = function(bookObj) {
        if(bookObj) {
          favoriteBooks.push(bookObj);
          return true;
        }
      }
      return { getBooks: getBooks,
        getBookDetails: getBookDetails
        addToFavorite: addToFavorite
      }
    }
  ]
);