Skip to content

Instantly share code, notes, and snippets.

@kevcha
Created August 6, 2013 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevcha/6163894 to your computer and use it in GitHub Desktop.
Save kevcha/6163894 to your computer and use it in GitHub Desktop.
Difference between Factory, Services and Providers @see https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ => Miško Hevery answers
Lets look at the simplest scenario
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
in this case the injector simple returns the value as is. But what if you want to compute the value. Then use a factory
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(a).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(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
then to instantiate you would have to write
provide.factory('greeter', function(a) {
return new Greeter(a);
});
Then we could ask for 'greeter' in controller like this
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
But that is way too wordy a shorter way to write this would be
provider.service('greeter', Greeter);
But what it 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(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
we can then do this
angular.module('abc', []).configure(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter.greet()).toEqual('Halo 123');
}
But it turns out that angular only understands provide.provider, all other ones are derived.
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;
});
};
Then =>
On Friday, August 17, 2012 11:00:53 AM UTC-7, ben.clin...@gmail.com wrote:
In order to get this straight in my own head I have created a very simple demo which can be viewed at http://jsbin.com/ohamub/1/edit
There are comments in the code illustrating the primary differences but I will expand on them a bit here. As a note, I am just getting my head around this so if I say anything that is wrong please let me know.
Services
Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided the actual function reference passed to module.service.
NO, you will get an instance of the function. In other words new FunctionYouPassedToService().
Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference. Could also be run with injectedArg.call( this ) or similar.
Factories
Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided the value that is returned by invoking the function reference passed to module.factory.
CORRECT
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.
Providers
Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided the value that is returned by invoking the $get method of the function reference passed to module.provider.
ALMOST
you will be provided with new ProviderFunction().$get(). The constructor function is instantiated before the $get method is called.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances but that requires some sort of configuration before being injected. Perhaps useful for classes that are reusable across projects? Still kind of hazy on this one.
Providers have the advantage that they can be configured during the module configuration phase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment