
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 objectlogin
: A method to log in a user and savesessionToken
to cookieslogout
: A method to log a user out of a web service and remove thesessionToken
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 categoryAuthor
: Fetch books for a specific authorSortBy
: 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 } } ] );