AngularJS中的服务、提供商和工厂之间有什么区别?
当前回答
工厂:您实际在工厂内部创建对象并将其返回的工厂。service:您只有一个使用this关键字定义函数的标准函数的服务。provider:您定义了一个$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;
});
};
Angular文档摘要:
有五种配方类型定义了如何创建对象:Value,工厂、服务、供应商和常量。工厂和服务是最常用的配方。它们之间的唯一区别是,Service配方对自定义类型的对象更有效,而Factory可以生成JavaScript原语和函数。提供者配方是核心配方类型,所有其他配方都只是其语法上的糖。提供程序是最复杂的配方类型。除非您正在构建一段需要全局配置的可重用代码,否则您不需要它。
SO的最佳答案:
https://stackoverflow.com/a/26924234/165673(<--良好)https://stackoverflow.com/a/27263882/165673https://stackoverflow.com/a/16566144/165673
另外一个澄清是,工厂可以创建函数/原语,而服务不能。看看这个基于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/
所有的好答案都已经有了。我想在服务和工厂方面再补充几点。以及服务/工厂之间的差异。你也可以有这样的问题:
我应该使用服务还是工厂?有什么不同?他们的行为是否相同?
让我们从服务和工厂之间的区别开始:
两者都是Singleton:每当Angular第一次发现它们作为依赖项时,它都会创建服务/工厂的单个实例。创建实例后,将永远使用同一实例。可用于对具有行为的对象进行建模:它们都可以有方法、内部状态变量等。尽管编写代码的方式会有所不同。
服务:
服务是一个构造函数,Angular将通过调用newyourServiceName()来实例化它。这意味着一些事情。
函数和实例变量将是它的财产。您不需要返回值。当Angular调用new yourServiceName()时,它将接收此对象以及您在其上放置的所有财产。
示例:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
当Angular将此MyService服务注入控制器时取决于它,该控制器将获得它可以调用的MyService上的函数,例如MyService.aServiceMethod()。
注意:
由于构造的服务是一个对象,因此当调用它们时,它内部的方法可以引用它:
angular.service('ScoreKeeper', function($http) {
this.score = 0;
this.getScore = function() {
return this.score;
};
this.setScore = function(newScore) {
this.score = newScore;
};
this.addOne = function() {
this.score++;
};
});
例如,如果您通过从服务器$http.get('/score').then(ScoreKeeper.setScore)获取分数来初始化分数,那么您可能会尝试在承诺链中调用ScoreKeeper。这样做的问题是,ScoreKeeer.setScore将在该绑定为空的情况下被调用,并且您会收到错误。更好的方法是$http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))。无论您是否选择在服务方法中使用它,请注意如何调用它们。
从服务返回值:
由于JavaScript构造函数的工作方式,若从构造函数函数返回一个复杂值(即Object),调用者将获得该Object而不是该实例。
这意味着你基本上可以从下面复制粘贴工厂示例,用服务替换工厂,它会起作用:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
因此,当Angular使用新的MyService()构造服务时,它将获得该api对象而不是MyService实例。
这是任何复杂值(对象、函数)的行为,但不是基本类型的行为。
工厂:
工厂是一个返回值的普通旧函数。返回值是注入到依赖于工厂的事物中的值。Angular中的一个典型工厂模式是返回一个具有函数作为财产的对象,如下所示:
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
工厂依赖项的注入值是工厂的返回值值,并且它不必是对象。这可能是一种功能
以上1和2个问题的答案:
大多数情况下,只要坚持使用工厂就可以了。他们的行为更容易理解。别无选择关于是否返回一个值,此外,没有错误如果你做错事,就会被介绍。当我谈论注射时,我仍然将其称为“服务”但它们是依赖关系。服务/工厂行为非常相似,有些人会说任何一个都很好。这有点正确,但我觉得遵循约翰·帕帕风格指南的建议,坚持工厂**
本质上,供应商、工厂和服务都是服务。工厂是服务的一种特殊情况,您只需要一个$get()函数,这样您就可以用更少的代码编写它。
服务、工厂和供应商之间的主要区别在于其复杂性。服务是最简单的形式,工厂更健壮,提供者在运行时可配置。
以下是何时使用每一项的摘要:
工厂:需要根据其他数据计算您提供的值。
服务:您正在返回带有方法的对象。
提供者:您希望能够在配置阶段配置将在创建之前创建的对象。在应用程序完全初始化之前,主要在应用程序配置中使用Provider。
推荐文章
- 如何设置一个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路由不带散列“#”
- 单击表单中的按钮会刷新页面
- 典型的AngularJS工作流程和项目结构(使用Python Flask)