素材巴巴 > 程序开发 >

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

程序开发 2023-09-19 16:05:29

The difference between Service, Provider, and Factory in AngularJS

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

 

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

    

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


    Provider


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

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”的字符串,但也可以是方法或者一个对象。

    

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


    Angular仅仅得到了一次值

    

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

    

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

   


mod.provider("myProvider", function() {this.$get = function() {console.log("MyProviderFunction.$get() called."); // ADDED this linereturn "My Value";};
 });mod.controller("MyController", function(myProvider) {console.log("MyController - myProvider: " + myProvider);
 });mod.controller("MyController2", function(myProvider) { // ADDED this controllerconsole.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 constructorthis.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 constructorthis.getValue = function() {return "My Value";};};
 });


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

mod.factory("myProvider", function() {console.log("Factory function called.");return new function() { // INLINED our object constructorthis.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 beforethis.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" suffixmyProviderProvider.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/


标签:

上一篇: Vue.js 生命周期详解 下一篇:
素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。