您的位置:首页 > Web前端 > AngularJS

AngularJS: Service v. Factory

2014-03-29 14:30 204 查看
From: http://www.tuicool.com/articles/zumyQv
In various AngularJS tutorials and documentation, the authors choose to use
service
or
factory
but
don't explain why you would use one or the other. Few mention that
value
and
constant
are
also options.

Let's see why you would use one over the other. We should also understand how providers work:


provider

Here's the source for the
provider
method:

function provider(name, provider_) {
    if (isFunction(provider_) || isArray(provider_)) {
        provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
        throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
}


name
is a string.
provider_
can
be one of three things:

function
If a function is passed in, the function is called with dependency injection and should return an object
with a
$get
method.

array
An array will be treated like a function using Inline Annotation . It must also return an object with
a
$get
method.

object
If an object is passed in, it is simply expected to have a
$get
method.

Whatever the second arg to
provider
is,
you eventually end up with an object that has a
$get
method.
Here's an example showing what happens:

// You can run this

// Create a module
var hippo = angular.module('hippo', []);

// Register an object provider
hippo.provider('awesome', {
    $get: function() {
        return 'awesome data';
    }
});

// Get the injector (this happens behind the scenes in angular apps)
var injector = angular.injector(['hippo', 'ng']);

// Call a function with dependency injection
injector.invoke(function(awesome) {
    console.log('awesome == ' + awesome);
});


Once you understand providers you will see that
factory
,
service
,
value
and
constant
are
just convenience methods for making providers.


factory

Here's the source:

function factory(name, factoryFn) {
    return provider(name, { $get: factoryFn });
}


So it lets you shorten the
awesome
provider
creation code to this:

hippo.factory('awesome', function() {
    return 'awesome data';
})



service

Here's the source:

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
        return $injector.instantiate(constructor);
    }]);
}


So it lets you make a factory that will instantiate a "class". For example:

var gandalf = angular.module('gandalf', []);

function Gandalf() {
    this.color = 'grey';
}
Gandalf.prototype.comeBack = function() {
    this.color = 'white';
}

gandalf.service('gandalfService', Gandalf);

var injector = angular.injector(['gandalf', 'ng']);

injector.invoke(function(gandalfService) {
    console.log(gandalfService.color);
    gandalfService.comeBack()
    console.log(gandalfService.color);
});


The above code will instantiate
Gandalf
,
but remember that everything that uses the service will get the same instance! (which is a good thing).


value

Here's the source:

function value(name, value) {
    return factory(name, valueFn(value));
}


Using
value
would let you shorten
the
awesome
provider to:

hippo.value('awesome', 'awesome data');



constant

Here's the source

function constant(name, value) {
    providerCache[name] = value;
    instanceCache[name] = value;
}


constant
differs from
value
in
that it's accessible during config. Here's how you use it:

var joe = angular.module('joe', []);

joe.constant('bobTheConstant', 'a value');
joe.value('samTheValue', 'a different value');

joe.config(function(bobTheConstant) {
    console.log(bobTheConstant);
});

joe.config(function(samTheValue) {
    console.log(samTheValue);
});

// This will fail with "Error: Unknown provider: samTheValue from joe"
var injector = angular.injector(['joe', 'ng']);


Read Module Loading & Dependencies in the Modules doc for more information on usage.


In summary

If you want your function to be called like a normal function, use
factory
.
If you want your function to be instantiated with the
new
operator,
use
service
. If you don't know
the difference, use
factory
.

This is the (great) documentation for each function in the AngularJS source:

factory

A short hand for configuring services if only `$get` method is required.

service

A short hand for registering service of given class.

value

A short hand for configuring services if the `$get` method is a constant.

constant

A constant value, but unlike {@link AUTO.$provide#value value} it can be injected into configuration function (other modules) and it is not interceptable by {@link AUTO.$provide#decorator decorator}.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: