Providers, Factories and Services in AngularJS

Providers, Factories and Services in AngularJS

0 18525
Many developers ask this question, trying to understand this dependency injection, other differences, advantages and disadvantages of these AngularJS objects. In this article I will try to explain in details everything we know about the providers, services and factories.
Services and Factories in AngularJS The answer come to be around service and factory, and this difference between them is like the difference between some function and an object.

Factory Provider

  • Gives us the function’s return value ie. You create an object, add properties to it, then return that same object. When you pass this service into your controller, those properties on the object will now be available in that controller through your factory (hypothetically)
  • Singleton
  • Reusable components
  • Can use other dependencies
  • Usually used when the service instance requires complex creation logic
  • Used for non configurable services
  • If you’re using an object, you could use the factory provider

Service Provider

  • Gives us the instance of a function (object). You instantiated with the ‘new’ keyword and you will add properties to ‘this’ and the service will return ‘this’. When you pass the service into your controller, those properties on ‘this’ will now be available on that controller through your service (hypothetically)
  • Singleton and will only be created once
  • Reusable components
  • Dependencies are injected as constructor arguments
  • Used for simple creation logic
  • If you’re using a class you could use the service provider
Provider in AngularJS Provider and Factories in AngularJS

Services

Syntax: module.service('serviceName', function); Result: When declaring serviceName as an injectable argument you will be provided with an instance of the function. In other words new FunctionYouPassToService()

Factories

Syntax: module.factory('factoryName', function); Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory

Providers

Syntax: module.provider('providerName', function); Result: When declaring providerName as an injectable argument you will be provided with (new ProviderFunction()).$get(). The constructor function is instantiated before the $get method is called – ProviderFunction is the function reference passed to module.provider Providers have the advantage that they can be configured during the module configuration phase. Example:
provide.value('variable', 123);
function Controller(variable) {
  expect(variable).toEqual(123);
}
In this case the injector simply returns the value as is. But what if you want to compute the value? Then use a factory:
provide.factory('myfactory', function(variable) {
  return variable * 2;
});
function Controller(myfactory) {
  expect(myfactory).toEqual(246);
}
So factory is a function which is responsible for creating the value. Notice that the factory function can ask for other dependencies. But what if you want to be more OO and have a class called Greeter?
function Greeter(name) {
  this.greet = function() {
    return 'Hello ' + name;
  }
}
Then to instantiate you would have to write
provide.factory('greeter', function(name) {
  return new Greeter(name);
});
Then we could ask for ‘greeter’ in controller like this
function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello John');
}
But that is way too wordy. A shorter way to write this would be provider.service(‘greeter’, Greeter); But what if we wanted to configure the Greeter class before the injection? Then we could write
provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }
  function Greeter(name) {
    this.greet = function() {
      return salutation + ' ' + name;
    }
  }
  this.$get = function(name) {
    return new Greeter(name);
  };
});
Then we can do this:
angular.module('abc', []).config(function(greeter2Provider) {
  greeter2Provider.setSalutation('Hola');
});
function Controller(greeter2) {
  expect(greeter2.greet()).toEqual('Hola John');
}
As a side note, service, factory, and value are all derived from provider.
provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}
provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}
provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};

Summary:

Factory use a factory function which return a service instance. serviceInstance = fnFactory(); Service use a constructor function and Angular invoke this constructor function using ‘new’ keyword for creating the service instance. serviceInstance = new fnServiceConstructor(); Provider defines a providerConstructor function, this providerConstructor function defines a factory function $get . Angular calls $get() to create the service object. Provider syntax has an added advantage of configuring the service object before it get instantiated. serviceInstance = $get();

SIMILAR ARTICLES


NO COMMENTS

Leave a Reply