AngularJS中的服务、提供商和工厂之间有什么区别?
当前回答
服务与供应商与工厂:
我试图保持简单。这都是关于JavaScript的基本概念。
首先,我们来谈谈AngularJS中的服务!
什么是服务:在AngularJS中,Service只是一个单独的JavaScript对象,可以存储一些有用的方法或财产。此单例对象是根据ngApp(Angular应用程序)创建的,它在当前应用程序中的所有控制器之间共享。当Angularjs实例化服务对象时,它使用唯一的服务名称注册该服务对象。因此,每当我们需要服务实例时,Angular都会在注册表中搜索该服务名称,并返回对服务对象的引用。这样我们就可以调用方法、访问服务对象上的财产等。您可能会有疑问,是否也可以在控制器的范围对象上放置财产和方法!所以为什么需要服务对象?答案是:服务在多个控制器范围内共享。如果您将一些财产/方法放在控制器的范围对象中,它将仅对当前范围可用。但当您在服务对象上定义方法和财产时,它将全局可用,并且可以通过注入该服务在任何控制器的范围内访问。
所以,若有三个控制器作用域,让它是controllerA、controllerB和controllerC,它们都将共享同一个服务实例。
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
如何创建服务?
AngularJS提供了注册服务的不同方法。在这里,我们将集中讨论工厂(..)、服务(..)和提供者(..)三种方法;
使用此链接进行代码参考
工厂功能:
我们可以如下定义工厂函数。
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJS提供了“factory('serviceName',fnFactory)”方法,该方法包含两个参数,serviceName和一个JavaScript函数。Angular通过调用函数fnFactory()创建服务实例,如下所示。
var serviceInstace = fnFactory();
传递的函数可以定义一个对象并返回该对象。AngularJS只是将此对象引用存储到作为第一个参数传递的变量中。从fnFactory返回的任何内容都将绑定到serviceInstance。除了返回对象之外,我们还可以返回函数、值等,无论我们将返回什么,都将可用于服务实例。
例子:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
服务功能:
service('serviceName',function fnServiceConstructor(){})
这是另一种方式,我们可以注册服务。唯一的区别是AngularJS尝试实例化服务对象的方式。这次angular使用“new”关键字并调用如下所示的构造函数。
var serviceInstance = new fnServiceConstructor();
在构造函数中,我们可以使用“this”关键字向服务对象添加财产/方法。例子:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
提供程序功能:
Provider()函数是创建服务的另一种方法。让我们有兴趣创建一个只向用户显示一些问候信息的服务。但我们也希望提供一个功能,用户可以设置自己的问候语。从技术上讲,我们希望创建可配置的服务。我们如何做到这一点?必须有一种方法,让应用程序可以传递他们的自定义问候消息,Angularjs将其提供给创建我们服务实例的工厂/构造函数。在这种情况下,provider()函数完成任务。使用provider()函数,我们可以创建可配置的服务。
我们可以使用下面给出的提供程序语法创建可配置的服务。
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
提供程序语法如何在内部工作?
1.提供程序对象是使用我们在提供程序函数中定义的构造函数创建的。
var serviceProvider = new serviceProviderConstructor();
2.我们在app.config()中传递的函数被执行。这被称为配置阶段,在这里我们有机会定制我们的服务。
configureService(serviceProvider);
3.最后通过调用serviceProvider的$get方法创建服务实例。
serviceInstance = serviceProvider.$get()
使用provide语法创建服务的示例代码:
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
工作演示
摘要:
工厂使用返回服务实例的工厂函数。serviceInstance=fnFactory();
服务使用构造函数,Angular使用“new”关键字调用此构造函数以创建服务实例。serviceInstance=新的fnServiceConstructor();
Provider定义了providerConstructor函数,此providerConstructer函数定义了工厂函数$get。Angular调用$get()来创建服务对象。提供程序语法还有一个额外的优点,即在服务对象实例化之前对其进行配置。serviceInstance=$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;
});
};
JS Fiddle演示
工厂/服务/供应商的“Hello world”示例:
var myApp=角度模块('myApp',[]);//服务风格,可能是最简单的myApp.service('helloWorldFromService',函数(){this.sayHello=函数(){return“你好,世界!”;};});//工厂风格,更加复杂myApp.factory('helloWorldFromFactory',函数(){返回{sayHello:函数(){return“你好,世界!”;}};});//提供程序风格、全面、可配置版本myApp.provider('helloWorld',函数(){this.name='默认值';这一点$get=函数(){var名称=this.name;返回{sayHello:函数(){return“您好,”+name+“!”;}}};this.setName=函数(名称){this.name=名称;};});//嘿,我们可以配置提供者!myApp.config(函数(helloWorldProvider){helloWorldProvider.setName('World');});函数MyCtrl($scope、helloWorld、helloWorldFromFactory、helloWorldFromService){$scope.hellos=[helloWorld.sayHello(),helloWorldFromFactory.sayHello(),helloWorldFromService.sayHello()];}<script src=“https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js“></script><body ng app=“myApp”><div ng controller=“MyCtrl”>{{hellos}}</div></body>
服务与供应商与工厂:
我试图保持简单。这都是关于JavaScript的基本概念。
首先,我们来谈谈AngularJS中的服务!
什么是服务:在AngularJS中,Service只是一个单独的JavaScript对象,可以存储一些有用的方法或财产。此单例对象是根据ngApp(Angular应用程序)创建的,它在当前应用程序中的所有控制器之间共享。当Angularjs实例化服务对象时,它使用唯一的服务名称注册该服务对象。因此,每当我们需要服务实例时,Angular都会在注册表中搜索该服务名称,并返回对服务对象的引用。这样我们就可以调用方法、访问服务对象上的财产等。您可能会有疑问,是否也可以在控制器的范围对象上放置财产和方法!所以为什么需要服务对象?答案是:服务在多个控制器范围内共享。如果您将一些财产/方法放在控制器的范围对象中,它将仅对当前范围可用。但当您在服务对象上定义方法和财产时,它将全局可用,并且可以通过注入该服务在任何控制器的范围内访问。
所以,若有三个控制器作用域,让它是controllerA、controllerB和controllerC,它们都将共享同一个服务实例。
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
如何创建服务?
AngularJS提供了注册服务的不同方法。在这里,我们将集中讨论工厂(..)、服务(..)和提供者(..)三种方法;
使用此链接进行代码参考
工厂功能:
我们可以如下定义工厂函数。
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJS提供了“factory('serviceName',fnFactory)”方法,该方法包含两个参数,serviceName和一个JavaScript函数。Angular通过调用函数fnFactory()创建服务实例,如下所示。
var serviceInstace = fnFactory();
传递的函数可以定义一个对象并返回该对象。AngularJS只是将此对象引用存储到作为第一个参数传递的变量中。从fnFactory返回的任何内容都将绑定到serviceInstance。除了返回对象之外,我们还可以返回函数、值等,无论我们将返回什么,都将可用于服务实例。
例子:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
服务功能:
service('serviceName',function fnServiceConstructor(){})
这是另一种方式,我们可以注册服务。唯一的区别是AngularJS尝试实例化服务对象的方式。这次angular使用“new”关键字并调用如下所示的构造函数。
var serviceInstance = new fnServiceConstructor();
在构造函数中,我们可以使用“this”关键字向服务对象添加财产/方法。例子:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
提供程序功能:
Provider()函数是创建服务的另一种方法。让我们有兴趣创建一个只向用户显示一些问候信息的服务。但我们也希望提供一个功能,用户可以设置自己的问候语。从技术上讲,我们希望创建可配置的服务。我们如何做到这一点?必须有一种方法,让应用程序可以传递他们的自定义问候消息,Angularjs将其提供给创建我们服务实例的工厂/构造函数。在这种情况下,provider()函数完成任务。使用provider()函数,我们可以创建可配置的服务。
我们可以使用下面给出的提供程序语法创建可配置的服务。
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
提供程序语法如何在内部工作?
1.提供程序对象是使用我们在提供程序函数中定义的构造函数创建的。
var serviceProvider = new serviceProviderConstructor();
2.我们在app.config()中传递的函数被执行。这被称为配置阶段,在这里我们有机会定制我们的服务。
configureService(serviceProvider);
3.最后通过调用serviceProvider的$get方法创建服务实例。
serviceInstance = serviceProvider.$get()
使用provide语法创建服务的示例代码:
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
工作演示
摘要:
工厂使用返回服务实例的工厂函数。serviceInstance=fnFactory();
服务使用构造函数,Angular使用“new”关键字调用此构造函数以创建服务实例。serviceInstance=新的fnServiceConstructor();
Provider定义了providerConstructor函数,此providerConstructer函数定义了工厂函数$get。Angular调用$get()来创建服务对象。提供程序语法还有一个额外的优点,即在服务对象实例化之前对其进行配置。serviceInstance=$get();
此答案针对主题/问题
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块提供
我的理解很简单。
工厂:您只需在工厂内部创建一个对象并返回它。
服务:
您只需要一个使用此关键字定义函数的标准函数。
供应商:
您定义了一个$get对象,它可以用于获取返回数据的对象。
推荐文章
- 在AngularJS中集成jQuery插件的正确方法
- 如何设置一个iframe src属性从一个变量在AngularJS
- 如何在Angular中使用$rootScope来存储变量?
- AngularJS:工厂和服务?
- 父ng-repeat从子ng-repeat的访问索引
- 无法解析类型为“Microsoft.AspNetCore.Http.IHttpContextAccessor”的服务
- AngularJS使用ng-class切换类
- 如何在Angular.js中配置不同的环境?
- 当使用ng-model时,输入文本框上的Value属性被忽略?
- 使用AngularJS跟踪谷歌分析页面视图
- 传递参数
- 在“DOMWindow”上执行“postMessage”失败:https://www.youtube.com !== http://localhost:9000
- Angular中相当于AngularJS $watch的东西是什么?
- AngularJS路由不带散列“#”
- 单击表单中的按钮会刷新页面