AngularJS中service与factory的使用

来源:互联网 发布:串行12864接单片机 编辑:程序博客网 时间:2024/05/02 01:28

翻译自Angular service or factory?(貌似要翻墙)

若觉得太长了,可直接跳到底部的总结。

在很多AngularJS的教程和文档中,作者时而使用service

,时而使用factory,但从来不解释为什么。更别说其实你还能用valueconstant了。

我们来看看在什么情况下你应该使用哪个。首先,我们也应该理解providers的工作方式:

provider

这是provieder方法的源码:

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 是字符串. provider_可以是这三种东西之一:

  1. 函数(function)

    如果传入的是一个函数,那么这个函数会被 dependency injection调用,并返回一个有$get方法的对象

  2. 数组(array)

    数组被视为使用Inline Annotation的函数, 它也必须返回一个有$get方法的对象。

  3. 对象(object)

    如果传入的是个对象,那么它应该是有$get方法的对象。

无论provider的第二个参数是什么,你最终都会个到一个拥有$get方法的对象。以这段代码为例:

// You can run this// Create a modulevar hippo = angular.module('hippo', []);// Register an object providerhippo.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 injectioninjector.invoke(function(awesome) {    console.log('awesome == ' + awesome);});

一旦你理解了provider,你就会发现factory, service, valueconstant只是生成provider的快捷方式

factory

这是源代码:

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

所以你可以简单的把一个名叫awesome的provider写成这个样子:

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

service

这是源代码:

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

所以这可以让你构建一个factory,用它可以初始化一个“类(class)”,比如说:

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);});

以上的代码会生成一个Gandalf(译注:即甘道夫,魔戒里的白胡子老头),但是请记住,使用同一个service返回的实例都是同一个实例(这是件好事)。

value

这是源代码:

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

value可以让你把awesome的缩短成这样:

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

constant

这是源代码:

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

constantvalue不同,constant在config的时候是可达的(accessible),如下例:

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']);

在Modules文档的Module Loading & Dependencies部分可以获得更多信息。

总结

如果你想像调用普通函数那样调用你的函数,用factory,如果你想用new操作符来实例化你的函数,那么使用service。如果你不知道这其中的区别在那里,那就用factory

以下是AngularJS源代码中,每个函数(很棒的)注释文档:

  1. factory

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

  2. service

    A short hand for registering service of given class.

  3. value

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

  4. 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}.