AngularJS中Provider、Service和Factory之间的不同

The difference between Service, Provider, and Factory in AngularJS

    如果你正在寻找不同,可能是因为你正在找出哪一个对于你才是合适的。或者是因为你已经遇到了它们三个,并且因为它们看起来相似而判断不同处。

 

如果你认为它们是相似的 - 你就答对了。它们是非常相似的。事实上,他们都是一样的本质

    

    他们都是provider。factory和service仅仅是provider的特殊实例,但是你能完成你想用provider做的所有事情。比如:


    Provider


    我们将创建一个provider,返回一个值并且简单的展示这个值。

<body ng-app="MyModule">
    <div ng-controller="MyController"></div>
</body>
var mod = angular.module("MyModule", []);

mod.provider("myProvider", function() {
    this.$get = function() {
        return "My Value";
    };
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider);
});

输出:
MyController - myProvider: My Value

       动态的例子可以看这里:JS Fiddle


    这里,如此一个“provider”意味着让你“provider”一个值。这个值可以是任何内容。在这种情况下,它是一个值为“My Value”的字符串,但也可以是方法或者一个对象。

    

    注意在接下来的代码示例中,我将排除<body>标签和<mod>定义,为了保持代码片段简短扼要。


    Angular仅仅得到了一次值

    

    注意,Angular仅仅“gets”一次值,无论provider被注入多少次。这意味着它曾仅仅调用$get()一次,存储在它提供的值中,并且每次给你相同的存储值。

    

    为了让你明白我说的,我将创建另一个controller然后带着输出状态再次注入到provider中,以至于你能看到发生了什么。

   

<div ng-controller="MyController"></div>
<div ng-controller="MyController2"></div>

mod.provider("myProvider", function() {
    this.$get = function() {
        console.log("MyProviderFunction.$get() called."); // ADDED this line
        return "My Value";
    };
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider);
});

mod.controller("MyController2", function(myProvider) { // ADDED this controller
    console.log("MyController2 - myProvider: " + myProvider);
});
输出:
MyProviderFunction.$get() called.
MyController - myProvider: My Value
MyController2 - myProvider: My Value


    在JS Fiddle中打开

    

    正如你能看到$get()方法刚只被调用了一次。

    

    注意,我们为provider写了一部分代码的目的仅仅是证明创建了一个$get()方法。为什么不代替给angular一个方法而是定义另一个方法(注:这里的意思是为什么要多定义一个$get方法),为什么不代替它,仅仅是给它我们想要直接运行的方法?对,这就是angular的factory。


    Factory


    有了factory你就可以提供方法体给$get方法,angular做剩下的事情。下面是新的代码,你将看到结果会相同。

mod.factory("myProvider", function() { // CHANGED “provider" to “factory"
    console.log("Factory function called.");
    return "My Value";
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider);
});

mod.controller("MyController2", function(myProvider) {
    console.log("MyController2 - myProvider: " + myProvider);
});

输出
Factory function called.
MyController - myProvider: My Value
MyController2 - myProvider: My Value

    在JS Fiddle中打开

    

    现在你可能想知道为什么你曾使用provider,但是factory可以用更少的代码完成同样的功能。有几个原因我稍后深入的说,现在我想继续说主题。

    

    目前为止,我们已经返回了一个简单的字符串值,但是在实践中我们可能更多次想返回的是一个对象。那么这不会改变之前的例子太多代码,我们就能很容易的把返回字符串变成一个对象。

     

    例如,让我们返回一个叫做getValue()的对象。现在有很多方法你可以在JavaScript中创建一个对象,我们将使用“构造对象”的方式创建一个方法,方法中用属性和方法填充一个对象,然后用new关键字实例化它。

function MyObject() { // ADDED our object constructor
    this.getValue = function() {
        return "My Value";
    };
}

mod.factory("myProvider", function() {
    console.log("Factory function called.");
    return new MyObject(); // CREATE an instance of our object
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider.getValue()); // CHANGED to call getValue()
});

mod.controller("MyController2", function(myProvider) {
    console.log("MyController2 - myProvider: " + myProvider.getValue()); // CHANGED to call getValue()
});

输出结果:
Factory function called.
MyController - myProvider: My Value
MyController2 - myProvider: My Value

    在JS Fiddle中打开

    

    现在,我想对这个做一个小的调整,因为它将很好地引导我们进入下一个概念。在我们的例子中,我们创建了“构造对象”方法MyObject,但是由于我们只实例化在一个地方,我们也可以使用匿名函数来代替。

    

    这是很小的改动,原代码:

function MyObject() {
    this.getValue = function() {
        return "My Value";
    };
}

mod.factory("myProvider", function() {
    console.log("Factory function called.");
    return new MyObject();
});

    改成:

mod.factory("myProvider", function() {
    console.log("Factory function called.");
    return new function() { // INLINED our object constructor
        this.getValue = function() {
            return "My Value";
        };
    };
});


    现在整个代码看起来如下:

mod.factory("myProvider", function() {
    console.log("Factory function called.");
    return new function() { // INLINED our object constructor
        this.getValue = function() {
            return "My Value";
        };
    };
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider.getValue());
});

mod.controller("MyController2", function(myProvider) {
    console.log("MyController2 - myProvider: " + myProvider.getValue());
});


       JS Fiddle中打开

    

    现在既然我们整个factory由一个单独的对象组成,如果我们只是给angular构造对象方法,代替必须写看起来时髦的factory岂不是更好。很好你很幸运,这确实是service所做的。


    service


    下面是相同的代码,用service代替factory

mod.service("myProvider", function() { // CHANGED "factory" to "service"
    // NOTE that the only function being passed is the object constructor from before
    this.getValue = function() {
        return "My Value";
    };
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider.getValue());
});

mod.controller("MyController2", function(myProvider) {
    console.log("MyController2 - myProvider: " + myProvider.getValue());
});

输出:
MyController - myProvider: My Value
MyController2 - myProvider: My Value


       JS Fiddle中打开


    Provider VS Factory VS Service


    正如概要,provider,factory和service都是provider。factory是provider的一个特例,在provider中当所有你需要的内容就是$get()。它允许你用少量的代码写。service是factory的一个特例,当你想返回一个新的对象,同样可以少写代码。


    该用哪个呢?


    答案是用你最熟悉的、能完成目标的版本。举个例子,你正返回一个现有的对象,这个对象被定义在其他需要构造参数的地方。你不能传递参数给service,因此你可以用factory代替它。

mod.factory("myProvider", function() {
    console.log("Factory function called.");
    return new SomeMessageBoxClass("custom argument");
});

    provider和factory之间一个主要的、紧要的因素是你是否能够配置这个对象,在它产生之前配置它。你可以通过调用module.config(),得到一个实例给provider自己(代替通过provider返回对象)。当你要注入的时候,你可以通过在provider名字的末尾添加“provider”。


    举个例子:

mod.provider("myProvider", function() {
    this.value = "My Value";

    this.setValue = function(newValue) {
        this.value = newValue;
    };

    this.$get = function() {
        return this.value;
    };
});

mod.controller("MyController", function(myProvider) {
    console.log("MyController - myProvider: " + myProvider);
});

mod.config(function(myProviderProvider) { // ADDED config section
    // Note the extra "Provider" suffix
    myProviderProvider.setValue("New Value");
});

    这包括使用三个provider:provider,factory和service。还有一个provider没提到的,就是另一个特殊的例子——value。

    

    如果你记得当我们第一次介绍factory时,我们给的简单的返回字符串的例子。代码如下:

mod.factory("myProvider", function() {
    return "My Value";
});

    我们当时已经使用了value,我们再一次用了少量的代码完成它。代码如下:

mod.value("myProvider", "My Value");

    该用哪个呢?想必当你想基于其他数据计算值的时候使用factory,比如数据来自另一个value或外部代码。再又或者,当你想计算值仅仅是当它第一次被请求的时候。代码如下:

// Example where factory depends on a "value" provider
mod.value("multiple", 3);
mod.factory("value", function(multiple) { 
    return 10 * multiple; 
});
// Example where factory depends on external data
mod.factory("value", function(multiple) { 
    var multiple = getDateFromExternalPage();
    return 10 * multiple; 
});

    是不是意味着value是另一种provider?好吧,我撒谎了,这是另一个和value相似但是又有两处不同的provider,这就是constant。

    

    value和constant之间的不同是当一个值指定为常量使用通常是在配置阶段。你可能还记得我之前提到的,provider使用在配置阶段,但service和factory不可以。

    

    同样是value和constant。constant可以使用在配置阶段,而value不可以。另一个区别是,顾名思义,你不能改变一个常量的值。它保存第一次赋值,如果你试图去赋不同的值会不起作用。例如:

mod.value("myValue", "First Assignment");
mod.value("myValue", "Second  Assignment");
mod.constant("myConstant", "First Assignment");
mod.constant("myConstant", "Second Assignment");

mod.controller("MyController", function(myValue, myConstant) {
    console.log("myValue: " + myValue);
    console.log("myConstant: " + myConstant);
});

输出:
myValue: Second Assignment
myConstant: First Assignment

    这是是使用说明:

value You are providing a simple literal value.
mod.value("myValue", 10);
    
constant You need to be able access that value during the configuration phase. (using.config())
mod.constant("myValue", 10);
mod.config(function(myValue) {
    console.log(myValue);
});
        
factory The value you are providing needs to be calculated based on other data.
mod.constant("myValue", 10);
mod.config(function(myValue) {
    console.log(myValue);
});
        
service You are returning an object with methods.
mod.service("myService", function() {
    var name = "Bob";
    this.setName = function(newName) {
        this.name = newName;
    };
    this.getName = function() {
        return this.name;
    }
});
        
provider You want to be able to configure, during the config phase, the object that is going to be created before it’s created.
mod.provider("greeter", function() {
    var name;

    this.setName = function(newName) {
        name = newName;
    };

    this.$get = function() {
        return new function() {
            this.sayHi = function() {
                console.log("Hi " + name;
            };
        };
    };
});

mod.config(function(greeterProvider) {
    greeterProvider.setName(“John");
});
        

    为了指出重点,这里最后用图片来说明provider,factory,service和value

An image of an AngularJS provider with the factory, value, and service portions highlighted.

angularjs-provider-service-factory-highlight-examples





原文地址:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值