AngularJS中service与factory的使用

翻译自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 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);
});

一旦你理解了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}.

猜你喜欢

转载自blog.csdn.net/seele52/article/details/12870893
今日推荐