在angualr应用中,factory方法是用来注册服务的最常规方式,其实总结了一下,一共有5种方式来创建服务:
1. factory()
factory方法是创建和配置服务最快捷的方式;接受两个参数:
name(字符串):需要注册的服务名;
getFn(函数):这个函数会在angularJs创建服务实例时被调用。
var formApp = angular.module("formApp",["ngRoute"]); formApp.factory("progress", function() {//service不能直接接收参数(服务除外),此处有坑 varprogress = {}; progress.prev= function(id) { varcurrentElement = document.getElementById(id); currentElement.className= ""; currentElement.className= "progressStep"; }; progress.next= function(id) { varcurrentElement = document.getElementById(id); currentElement.className= ""; currentElement.className= "progressStep activeStep"; }; progress.init= function(id, defaultArr) { varcurrentIndex = defaultArr.indexOf(id); for(i = 0; i <= currentIndex; i++) { varcurrentElement = document.getElementById(defaultArr[i]); currentElement.className= ""; currentElement.className= "progressStep activeStep"; } } returnprogress; });
这是一个进度条的服务;我们知道服务是单例的对象,getFn在应用的生命周期内只会被调用一次,同其他angularJs服务一样,在定义服务时,getFn函数可以接受一个包含被注入对象的数组或函数;需要指出的是factory方式创建服务需要返回一个对象;当然这个返回值可以是一个简单的数据类型,函数,或者对象。
2. service
使用service方式可以注册一个支持构造函数的服务,容许我们为这个服务对象注册一个构造函数。接受两个参数。
name(字符串):要注册的服务名称;
constructor(函数):构造函数,我们调用它来实例化对象。
var SendData = function($http) { varparseParam = function(url, param) { varparams = JSON.stringify(param); returnurl + "=" + "'" +params + "'"; }; this.postData= function (url, param) { varpostURL = url +".action" + "?" + parseParam(url, param); return$http({method:"POST", url:postURL}); }; this.getData= function (url, param) { varpostURL = url +".action" + "?" + parseParam(url, param); return$http({method:"GET", url:postURL}); } } formApp.service("AjaxUtil",SendData);
service()函数会在创建实例时通过new关键字来实例化服务对象;this指针实际就值向了AjaxUtil;这样如果想使用该服务,就可以直接注入AjaxUtil服务,就可以。
3. provider
实际上在angularJs的源码中,所有的服务工厂都是由$provider服务创建的;$provider服务负责在运行时初始化这个提供者。
提供者是一个具有$get()方法的对象,$injector通过调用$get方法创建服务的实例。$provider提供了数个不同的API用于创建服务,每个方法都用各自的特殊用途。
所有的创建服务的方法都构建在provider方法之上。Provider方法负责在$providerCache中注册服务。
从技术上来讲,当我们传入的函数就是$get()时;factory函数就是provider方法注册服务的简略形式。比如下面两种创建服务的方式(实际上是等价的)。
angular.module("formApp").factory("getUserInfro",function() { return{"username":"jxj","work":"FED",emai:"[email protected]"}; }); angular.module("formApp").provider("getUserInfro",{$get:function() { return{"username":"jxj","work":"FED",emai:"[email protected]"}; }});
是否可以一直使用.factory方法来代替provider?
答案取决于是否需要用AngularJs的config()函数来对provider方法放回的五福进行额外的扩展配置。同其他创建服务的方式不同,config方法可以被注入特殊的参数。比如,我们希望在应用启动前配置myPath的Url:
formApp.provider("AjaxUtil",function() { //默认的私有变量 var myPath = "http://jxj.com"; var setPath = function(path) { //通过config改版默认的属性 myPath = url; }; this.$get = function($http) { var obj = {}; var parseParam = function(url, param) { var params = JSON.stringify(param); return url + "=" + "'"+params + "'"; }; obj.postData = function (url, param) { var postURL = url +".action" +"?" + parseParam(url, param); return $http({method:"POST",url:postURL}); }; obj.getData = function (url, param) { var postURL = url +".action" +"?" + parseParam(url, param); return $http({method:"GET",url:postURL}); }; return obj; } });
通过使用provider方法,可以在多个应用使用同一个服务时,获得更强的拓展性,特别是在不同应用或者开源社区共享服务时。
在上面的李自重provider方法在文本AjaxUtil后添加provider生成一个新的提供者,AjaxUtilProivder可以被注入到config函数中。
formApp.config(function(AjaxUtilProvider) { AjaxUtilProvider.setPath("http://jiaxiangjun.com"); });
如果希望在config函数中可以对服务惊醒配置,必须用provider来定义服务。Provider方法为服务注册提供者,接受两个参数。
name()字符串:providerCache中注册的名字;name+provider会成为服务的提供者,也是服务实例的名字。
aProvider(对象、函数、数组)
如果aProvider是函数,那么他会通过依赖注入被调用,并且负责通过$get方法返回一个对象。
如果是一个数组,会被当做一个带有行内依赖注入声明的函数来处理;数组的最后一个元素应该是函数,可以返回一个带有$get方法。
Provider函数返回一个已经注册的提供者实例。
直接providerAPI是最原始的创建服务的方法:
angular.module("myApp", []).provider("userService", { favoriteColor:null, setFavoriteColor:function(newColor) { this.favoriteColor =newColor; }, $get:function($http) { return { "name":"Ari", getFavoriteColor:function(){ returnthis.favoriteColor || "unkown"; } }; } });
用这个方法创建服务,必须返回一个定义有$get()函数的对象,否则会导致错误;可以通过注入器来实例化服务。
var injector = angular.injector(["myApp"]); injector.invoke( ["userService",function(userService) { //todo smething }]);
Provider非常强大,可以让我们在不同的应用中共享服务。
4. constant
可以将一个已经存在的变量值注册为服务,冰晶其注入到应用的其他部分;例如,假设我们需要一个apiKey,可以用constant将其当做常量保存下来。
接受两个参数。
name(字符串):需要注册常量的名字;
value(常量):需要注入的常量的值。
angular.module("myApp").constant("apiKey","jiaxiangjun"); //这个常量服务可以想其他服务一样被注入到配置函数中 angular.module("myController",function($scope, apiKey) { //to do something })
5. value
如果服务的$get方法返回的是一个常量,那就没必要定义一个包含复杂功能的完整服务,可以通过value函数方便地注册服务,接收两个参数。
name(字符串),注册的服务名;
value,将这个值作为可以注入的实例返回。
Value方法返回已name参数的值为名称的注册后的服务实例。
angular.module("myApp").value("api","jiaxiangjun");
何时使用value,constant
主要的区别在于,常量可以注入到配置函数中,而value不行;
一般来讲,value来注册服务对象或函数,用constant来配置数据。