AngularJS中的服务、提供商和工厂之间有什么区别?
当前回答
另外一个澄清是,工厂可以创建函数/原语,而服务不能。看看这个基于Epokk的jsFiddle:http://jsfiddle.net/skeller88/PxdSP/1351/.
工厂返回一个可以调用的函数:
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
工厂还可以返回具有可调用方法的对象:
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
该服务返回一个具有可调用方法的对象:
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
有关详细信息,请参阅我写的关于差异的帖子:http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
其他回答
此答案针对主题/问题
Factory、Service和Constant是如何在提供者配方之上添加语法糖的?
OR
工厂、服务和供应商在内部是怎样的
基本上发生的是
当您创建factory()时,它会将第二个参数中提供的函数设置为provider的$get并返回它(provider(name,{$get:factoryFn})),您所得到的只是provider,但除了$get之外没有其他属性/方法(这意味着您无法配置)
工厂源代码
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
};
当生成服务()时,它返回您提供factory()的函数,该函数注入构造函数(返回您在服务中提供的构造函数的实例)并返回它
服务源代码
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
};
因此,基本上在这两种情况下,您最终都会将providers$get设置为您提供的函数,但您可以提供$get以外的任何内容,因为您最初可以在provider()中为config块提供
所有服务均为单人服务;每个应用程序实例化一次。它们可以是任何类型,无论是原语、对象文本、函数,甚至是自定义类型的实例。
值、工厂、服务、常量和提供程序方法都是提供程序。他们教Injector如何实例化服务。
最冗长,但也是最全面的是提供者配方其余四种配方类型-价值、工厂、服务和常量-只是提供程序配方之上的语法糖。
Value Recipe是最简单的例子,您自己实例化服务,并将实例化的值提供给注入器。Factory配方为Injector提供了一个工厂函数,当它需要实例化服务时调用该函数。调用时,工厂函数创建并返回服务实例。服务的依赖项作为函数的参数注入。因此,使用此配方可增加以下功能:能够使用其他服务(具有依赖关系)服务初始化延迟/延迟初始化Service配方与Factory配方几乎相同,但这里Injector调用带有新运算符的构造函数,而不是工厂函数。提供商的配方通常是过度的。它通过允许您配置工厂的创建,增加了一个间接层。
只有当您想要公开API时,才应该使用Provider配方对于必须在应用程序启动。这通常只对可重复使用有用其行为可能需要在应用。常量配方与值配方类似,只是它允许您定义在配置阶段可用的服务。比使用Value配方创建的服务更快。与Values不同,它们不能使用decorator进行装饰。请参阅提供程序文档。
本质上,供应商、工厂和服务都是服务。工厂是服务的一种特殊情况,您只需要一个$get()函数,这样您就可以用更少的代码编写它。
服务、工厂和供应商之间的主要区别在于其复杂性。服务是最简单的形式,工厂更健壮,提供者在运行时可配置。
以下是何时使用每一项的摘要:
工厂:需要根据其他数据计算您提供的值。
服务:您正在返回带有方法的对象。
提供者:您希望能够在配置阶段配置将在创建之前创建的对象。在应用程序完全初始化之前,主要在应用程序配置中使用Provider。
我注意到了一些有趣的事情,当我和提供者一起玩的时候。
与服务和工厂相比,供应商对注射剂的可见性有所不同。如果您声明AngularJS“常量”(例如,myApp.constant('a','Robert');),您可以将其注入服务、工厂和提供商。
但是如果您声明一个AngularJS“value”(例如,myApp.value('b',{name:'Jones‘});),您可以将其注入服务和工厂,但不能注入提供程序创建函数。但是,您可以将其注入为提供者定义的$get函数中。AngularJS文档中提到了这一点,但很容易错过。您可以在%provide页面的value和constant方法部分找到它。
http://jsfiddle.net/R2Frv/1/
<div ng-app="MyAppName">
<div ng-controller="MyCtrl">
<p>from Service: {{servGreet}}</p>
<p>from Provider: {{provGreet}}</p>
</div>
</div>
<script>
var myApp = angular.module('MyAppName', []);
myApp.constant('a', 'Robert');
myApp.value('b', {name: 'Jones'});
myApp.service('greetService', function(a,b) {
this.greeter = 'Hi there, ' + a + ' ' + b.name;
});
myApp.provider('greetProvider', function(a) {
this.firstName = a;
this.$get = function(b) {
this.lastName = b.name;
this.fullName = this.firstName + ' ' + this.lastName;
return this;
};
});
function MyCtrl($scope, greetService, greetProvider) {
$scope.servGreet = greetService.greeter;
$scope.provGreet = greetProvider.fullName;
}
</script>
我的理解很简单。
工厂:您只需在工厂内部创建一个对象并返回它。
服务:
您只需要一个使用此关键字定义函数的标准函数。
供应商:
您定义了一个$get对象,它可以用于获取返回数据的对象。
推荐文章
- AngularJS控制器的生命周期是什么?
- $destroy是否删除事件监听器?
- 用布尔值将单选按钮绑定到模型
- AngularJS只适用于单页应用程序吗?
- angular.js中的内联条件
- 如何突出显示当前菜单项?
- 如何使用AngularJS获取url参数
- angularjs中的compile函数和link函数有什么区别
- 如何向一个5岁的孩子解释依赖注入?
- Ng-repeat结束事件
- 缓存一个HTTP 'Get'服务响应在AngularJS?
- 从ng-click获取原始元素
- Angular JS:当我们已经有了具有作用域的指令控制器时,指令的link函数还需要什么?
- Angularjs的ng-model不能在ng-if中工作
- AngularJS禁用了开发机器上的部分缓存