AngularJS中Provider、Service和Factory之间的不同
2015-12-04 13:40
766 查看
![](http://www.simplygoodcode.com/wp-content/uploads/2015/11/Blog-Post-Image.png)
如果你正在寻找不同,可能是因为你正在找出哪一个对于你才是合适的。或者是因为你已经遇到了它们三个,并且因为它们看起来相似而判断不同处。
如果你认为它们是相似的 -
你就答对了。它们是非常相似的。事实上,他们都是一样的本质。
他们都是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代替factorymod.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"); }); |
![](http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider-service-factory-highlight.png)
![](http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider-service-factory-highlight-examples.png)
原文地址:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
相关文章推荐
- Android IPC进程间通讯机制
- android之定时器AlarmManager
- axis备忘
- Windows XP Service Pack 3 RC1 v.3244 winxp补丁3 提供下载
- Run As Service runassrv.exe 详细参数第1/2页
- asp Driver和Provider两种连接字符串连接Access时的区别
- 安装MySQL在最后的start service停住了解决方法
- android使用Messenger绑定Service的多种实现方法
- asp.net Web Service 接口大量数据传输解决方案
- AngularJS基础教程之简单介绍
- Silverlight中动态获取Web Service地址
- JavaScript 设计模式学习 Factory
- android调用web service(cxf)实例应用详解
- 在Android中 获取正在运行的Service 实例
- php设计模式 Factory(工厂模式)
- ASP.NET State service状态服务的问题解决方法
- 错误类型:Provider (0x80004005)未指定的错误 的一个处理方法
- 卸载ZkeysPHP 后iis网站出现Service Unavailable 解决办法
- IIS Admin Service 服务因 2149647636 (0x80210514) 服务性错误而停止
- 基于Android ContentProvider的总结详解