AngularJS中的 "服务"、"供应商 "和 "工厂 "之间有什么区别?
我从AngularJS邮件列表中得到了[一个惊人的线程][1],它解释了服务与工厂与提供者以及它们的注入用法。汇编了答案。
语法。module.service( 'serviceName', function ); 结果。当声明serviceName作为一个可注入的参数时,你将得到一个函数的实例。换句话说, new FunctionYouPassedToService()。
module.service( 'serviceName', function );
new FunctionYouPassedToService()
语法:module.factory( 'factoryName', function ); 结果。当将factoryName声明为一个可注入的参数时,你将得到调用传递给module.factory的函数引用所返回的值。
module.factory( 'factoryName', function );
语法:module.provider( 'providerName', function ); 结果。当声明providerName作为一个可注入的参数时,你将得到 (new ProviderFunction()).$get()。构造函数在$get方法被调用之前被实例化 - ProviderFunction是传递给module.provider的函数引用。
module.provider( 'providerName', function );
(new ProviderFunction()).$get()
ProviderFunction
提供者的优点是可以在模块配置阶段进行配置。
提供的代码见here。
这里是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); }
所以factory是一个负责创建值的函数。注意,工厂函数可以要求其他的依赖性。
factory
但是,如果你想更加OO化,有一个叫做Greeter的类,怎么办?
function Greeter(a) { this.greet = function() { return 'Hello ' + a; } }
那么为了实例化,你就必须写上
provide.factory('greeter', function(a) { return new Greeter(a); });
然后,我们可以在控制器中要求'greeteter',像这样
function Controller(greeter) { expect(greeter instanceof Greeter).toBe(true); expect(greeter.greet()).toEqual('Hello 123'); }
但这太费字了。一个更简短的写法是:provider.service('greeter', Greeter);
provider.service('greeter', 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; }); };
[1]: https://groups.google.com/forum/#! msg/angular/56sdORWEoqg/HuZsOsMvKv4J
service
provider
var myApp = angular.module('myApp', []); //service style, probably the simplest one myApp.service('helloWorldFromService', function() { this.sayHello = function() { return "Hello, World!"; }; }); //factory style, more involved but more sophisticated myApp.factory('helloWorldFromFactory', function() { return { sayHello: function() { return "Hello, World!"; } }; }); //provider style, full blown, configurable version myApp.provider('helloWorld', function() { this.name = 'Default'; this.$get = function() { var name = this.name; return { sayHello: function() { return "Hello, " + name + "!"; } } }; this.setName = function(name) { this.name = name; }; }); //hey, we can configure a provider! myApp.config(function(helloWorldProvider){ helloWorldProvider.setName('World'); }); function 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> <div ng-controller="MyCtrl"> {{hellos}} </div>
我在玩弄供应商时注意到一些有趣的事情。
注入物的可见性对提供者来说与对服务和工厂来说是不同的。如果你声明一个AngularJS "常量"(例如,myApp.constant('a', 'Robert');),你可以将它注入到服务、工厂和提供者中。
myApp.constant('a', 'Robert');
但如果你声明一个AngularJS "值"(例如,myApp.value('b', {name: 'Jones'});),你可以把它注入服务和工厂,但不能注入提供者创建函数。然而,你可以把它注入你为提供者定义的`$get'函数中。AngularJS文档中提到了这一点,但很容易错过。你可以在%provide页面的值和常量方法部分找到它。
myApp.value('b', {name: 'Jones'});
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邮件列表中得到了[一个惊人的线程][1],它解释了服务与工厂与提供者以及它们的注入用法。汇编了答案。
服务
语法。
module.service( 'serviceName', function );
结果。当声明serviceName作为一个可注入的参数时,你将得到一个函数的实例。换句话说,
new FunctionYouPassedToService()
。Factories
语法:
module.factory( 'factoryName', function );
结果。当将factoryName声明为一个可注入的参数时,你将得到调用传递给module.factory的函数引用所返回的值。
提供者
语法:
module.provider( 'providerName', function );
结果。当声明providerName作为一个可注入的参数时,你将得到
(new ProviderFunction()).$get()
。构造函数在$get方法被调用之前被实例化 -ProviderFunction
是传递给module.provider的函数引用。提供者的优点是可以在模块配置阶段进行配置。
提供的代码见here。
这里是Misko的一个很好的进一步解释。
在这种情况下,注入器只是简单地返回原值。但如果你想计算这个值呢?那就用一个工厂
所以
factory
是一个负责创建值的函数。注意,工厂函数可以要求其他的依赖性。但是,如果你想更加OO化,有一个叫做Greeter的类,怎么办?
那么为了实例化,你就必须写上
然后,我们可以在控制器中要求'greeteter',像这样
但这太费字了。一个更简短的写法是:
provider.service('greeter', Greeter);
但如果我们想在注入前配置
Greeter
类呢?那么我们可以写然后我们就可以这样做了。
顺便提一下,"服务"、"工厂 "和 "价值 "都是由提供者派生的。
[1]: https://groups.google.com/forum/#! msg/angular/56sdORWEoqg/HuZsOsMvKv4J
[JS Fiddle Demo][1] 。
"Hello world "的例子,有
factory
/service
/provider
。我在玩弄供应商时注意到一些有趣的事情。
注入物的可见性对提供者来说与对服务和工厂来说是不同的。如果你声明一个AngularJS "常量"(例如,
myApp.constant('a', 'Robert');
),你可以将它注入到服务、工厂和提供者中。但如果你声明一个AngularJS "值"(例如,
myApp.value('b', {name: 'Jones'});
),你可以把它注入服务和工厂,但不能注入提供者创建函数。然而,你可以把它注入你为提供者定义的`$get'函数中。AngularJS文档中提到了这一点,但很容易错过。你可以在%provide页面的值和常量方法部分找到它。http://jsfiddle.net/R2Frv/1/