AngularJS中的服务、提供商和工厂之间有什么区别?
当前回答
我的理解很简单。
工厂:您只需在工厂内部创建一个对象并返回它。
服务:
您只需要一个使用此关键字定义函数的标准函数。
供应商:
您定义了一个$get对象,它可以用于获取返回数据的对象。
其他回答
我对此事的澄清:
基本上,所有提到的类型(服务、工厂、提供者等)都只是创建和配置全局变量(当然,这些变量对整个应用程序是全局的),就像老式的全局变量一样。
虽然不建议使用全局变量,但这些全局变量的实际用途是通过将变量传递给相关控制器来提供依赖注入。
在为“全局变量”创建值时有许多复杂程度:
常数这定义了一个在整个应用程序中不应修改的实际常量,就像其他语言中的常量一样(JavaScript缺少的)。价值这是一个可修改的值或对象,它充当一些全局变量,甚至可以在创建其他服务或工厂时注入(请参阅有关这些的详细信息)。然而,它必须是一个“文字值”,这意味着必须写出实际值,并且不能使用任何计算或编程逻辑(换句话说,39或myText或{prop:“value”}可以,但2+2不行)。工厂一个更一般的值,可以立即计算。它的工作原理是将一个函数传递给AngularJS,其中包含计算值所需的逻辑,AngularJS执行该函数,并将返回值保存在命名变量中。请注意,可以返回对象(在这种情况下,它的功能类似于服务)或函数(将作为回调函数保存在变量中)。服务服务是工厂的更精简版本,只有当值是对象时才有效,它允许直接在函数中写入任何逻辑(就像它是构造函数一样),以及使用this关键字声明和访问对象财产。供应商与工厂的简化版本的服务不同,提供程序是一种更复杂但更灵活的初始化“全局”变量的方法,最大的灵活性是从app.config中设置值的选项。它的工作方式类似于使用服务和提供者的组合,方法是向提供者传递一个函数,该函数具有使用this关键字声明的财产,该关键字可以从app.config中使用。然后它需要有一个单独的$.get函数,该函数由AngularJS在通过app.config文件设置上述财产后执行,该$.get功能的行为与上述工厂相同,因为它的返回值用于初始化“全局”变量。
我的理解很简单。
工厂:您只需在工厂内部创建一个对象并返回它。
服务:
您只需要一个使用此关键字定义函数的标准函数。
供应商:
您定义了一个$get对象,它可以用于获取返回数据的对象。
从AngularJS邮件列表中,我得到了一个令人惊叹的线程,它解释了服务与工厂与供应商以及它们的注入用法。编写答案:
服务
语法:module.service('serviceName',function);结果:当将serviceName声明为可注入参数时,将为您提供函数的实例。换句话说,新的FunctionYouPassedToService()。
工厂
语法:module.factory('factoryName',function);结果:当将factoryName声明为可注入参数时,将提供通过调用传递给module.factory的函数引用返回的值。
提供商
语法:module.provider('providerName',function);结果:当将providerName声明为可注入参数时,将提供(newProviderFunction())$get()。在调用$get方法之前实例化构造函数函数-ProviderFunction是传递给module.provider的函数引用。
提供程序的优点是可以在模块配置阶段进行配置。
请参阅此处获取提供的代码。
下面是Misko的进一步解释:
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
在这种情况下,注入器只是按原样返回值。但是如果您想计算该值呢?然后使用工厂
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
因此,工厂是一个负责创造价值的职能部门。注意,工厂函数可以要求其他依赖项。
但是,如果你想成为更多的OO,并拥有一个名为Greeter的类呢?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
然后,要实例化,必须编写
provide.factory('greeter', function(a) {
return new Greeter(a);
});
然后我们可以像这样在控制器中请求“问候者”
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
但这太啰嗦了。一个简短的写法是provider.service(“greeter”,greeter);
但是如果我们想在注入之前配置Greeter类呢?然后我们可以写
provide.provider('greeter2', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
然后我们可以这样做:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
顺便说一句,服务、工厂和价值都来自提供者。
provider.service = function(name, Class) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.instantiate(Class);
};
});
}
provider.factory = function(name, factory) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.invoke(factory);
};
});
}
provider.value = function(name, value) {
provider.factory(name, function() {
return value;
});
};
看完所有这些帖子后,这给我带来了更多的困惑……但所有的信息都是有价值的。。最后我找到了下表,它将通过简单的比较提供信息
注射器使用配方创建两种类型的对象:服务和特殊用途物体有五种配方类型定义了如何创建对象:Value,工厂、服务、供应商和常量。工厂和服务是最常用的配方。它们之间的唯一区别是,Service配方对自定义类型的对象更有效,而Factory可以生成JavaScript原语和函数。提供者配方是核心配方类型,所有其他配方都只是其语法上的糖。提供程序是最复杂的配方类型。除非您正在构建一段需要全局配置的可重用代码,否则您不需要它。除控制器外的所有特殊用途对象均通过工厂配方定义。
对于初学者来说:-这可能不正确的用例,但在高级别上,这是这三个用例的用例。
如果要在angular模块中使用,应将配置函数创建为提供程序
angular.module('myApp').config(函数($testProvider){$testProvider.someFunction();})
Ajax调用或第三方集成需要提供服务。对于数据操作,将其创建为工厂
对于基本场景,工厂和服务的行为相同。
我注意到了一些有趣的事情,当我和提供者一起玩的时候。
与服务和工厂相比,供应商对注射剂的可见性有所不同。如果您声明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>
推荐文章
- 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禁用了开发机器上的部分缓存