Angular之services

Constant

app.constant('fooConfig', {

config1: true,

config2: "Default config2"

});

     constant是个很有用的东东,我们经常会用于对directive之类的做配置信息。所以当你想创建一个directive,并且你希望能够做一些配置信息,同时给些默认的配置,constant是个不错的的选择。constant可以译作常量,因为我们所设置的值value是不能被改变的。其可以接受基础类型和object对象。

Value

app.value('fooConfig', {

config1: true,

config2: "Default config2 but it can changes"

});

      Value和上面的constant很相似,唯一是其在赋值后还可以被改变。它也被常用于directive配置信息。Value service只会保留values,我们不会在service中计算其值。

Factory

app.factory('foo', function() {

var thisIsPrivate = "Private";

function getPrivate() {

return thisIsPrivate;

}



return {

variable: "This is public",

getPrivate: getPrivate

};

});

     Factory是我们最常用的service。其很容易被理解。

     factory会返回一个object对象,至于你如何创建这个对象angular没任何限制。在示例中我选择了我喜欢的模式 Revealing module pattern,你可以选择其他你所希望的方式。

   如我之前所说,所有的services都是singleton的,所以当我们修改foo.variable的时候,会影响到其他使用的地方。

Service

app.service('foo', function() {

var thisIsPrivate = "Private";

this.variable = "This is public";

this.getPrivate = function() {

return thisIsPrivate;

};

});

   Service service和factory工作原理一样,只是他service接收的是一个构造函数,当第一次使用service的时候,angular会new Foo() 来初始化这个对象。以后的时候返回的都是同一个对象。

  实际上,下面是factory等价的写法:

app.factory('foo2', function() {

return new Foobar();

});

function Foobar() {

var thisIsPrivate = "Private";

this.variable = "This is public";

this.getPrivate = function() {

return thisIsPrivate;

};

}

    Foobar是一个class(类)在factory中我们手动初始化它,在返回它。和service一样Foobar class只在第一次初始化,并以后返回的都是同一个对象。

如果我们已经存在了一个class,那么我可以直接使用:

app.service('foo3', Foobar);

Provider

Provider 在angular中是个最终的高级选项,在上例factory中最后一个示例用provider将是如下:

app.provider('foo', function() {

return {

$get: function() {

var thisIsPrivate = "Private";

function getPrivate() {

return thisIsPrivate;

}

return {

variable: "This is public",

getPrivate: getPrivate

};

}

};

});

    provider带有一个$get的函数,其返回值将会被注入其他应用组件。所以我们注入foo到controller,我们注入的是$get 函数。

为什么我们还需要provider,factory实现不是更简单吗?这是因为我们能够在config 函数中配置provider。如下所示:

app.provider('foo', function() {

var thisIsPrivate = "Private";

return {

setPrivate: function(newVal) {

thisIsPrivate = newVal;

},

$get: function() {

function getPrivate() {

return thisIsPrivate;

}

return {

variable: "This is public",

getPrivate: getPrivate

};

}

};

});

app.config(function(fooProvider) {

fooProvider.setPrivate('New value from config');

});

   在这里我们把thisISPrivate移出了$get函数,我们创建了一个setPrivate函数,使其能够在config函数中修改thisIsPrivate变量。为什么我们需要这么做?在factory中加入一个setter不就好了吗?这是一个不同的意图。

   我们希望注入的是一个object对象,但是我们也希望能够提供一种方式去配置它。例如:一个包装了jsonp的资源resource的service,我们希望能够配置是从那个url获取资源,我们也将有个三方的消费者比如restangular允许我们去配置达到我们的目的。

   注意在config函数我们需要用nameProvider替代name,然而消费者只需要用name

   可以看见在在我们的应用程序中已经配置了一些services,比如$routeProvider,$locationProvider,配置我们的routes和html5model 调整适应。

额外的福利:

福利1:装潢器Decorator

如果你觉得我给你的foo service缺少了你所需要的greet方法,你需要改变API吗?不,你可以用更好的方法装潢:

app.config(function($provide) {

$provide.decorator('foo', function($delegate) {

$delegate.greet = function() {

return "Hello, I am a new function of 'foo'";

};


return $delegate;

});

});
    上例中$provide是angular内部用于创建我们所有service的service。如果我们希望在我们的应用程序中使用,我们可以手动的使用它(我们可以用$provide去装潢)。$provide有一个decorator的装潢函数,允许我们装潢我们的services,它接受我们所需要装潢的service的name和一个接受$delegate的回调函数,$delegate代表我们的原来的service实例。

   在这里我们可以装潢我们的service。在本例中我们在原来的service实例上增加了一个greet函数,在返回修改过后的service。当我们消费这个service的时候,它将会包含一个greet的函数,你可以在下面的try it中看见。

   对于使用来自第三方的service,当我们期望对其接口做一些扩展的时候,我们不需要copy它的代码到我们的项目来修改它,我们可以手动方便的使用装潢器去实现我们所想要的。

   注意:上文中说的常量constant是不可以被装潢的。

福利2:创建非单例对象

    如我们所知所有的service都是单例的,但是我们仍然可以创建一个非单例的对象。在我们深入之前,我们必须认识到大多数场景我们都会期望是个单例的service,我们也不会去改变这种机制。换句话在很少的场景中我们需要每次生成一个新的object对象。如下:

app.config(function($provide) {

$provide.decorator('foo', function($delegate) {

$delegate.greet = function() {

return "Hello, I am a new function of 'foo'";

};


return $delegate;

});

});

    上例中$provide是angular内部用于创建我们所有service的service。如果我们希望在我们的应用程序中使用,我们可以手动的使用它(我们可以用$provide去装潢)。$provide有一个decorator的装潢函数,允许我们装潢我们的services,它接受我们所需要装潢的service的name和一个接受$delegate的回调函数,$delegate代表我们的原来的service实例。

   在这里我们可以装潢我们的service。在本例中我们在原来的service实例上增加了一个greet函数,在返回修改过后的service当我们消费这个service的时候,它将会包含一个greet的函数,你可以在下面的try it中看见。

   对于使用来自第三方的service,当我们期望对其接口做一些扩展的时候,我们不需要copy它的代码到我们的项目来修改它,我们可以手动方便的使用装潢器去实现我们所想要的。

   注意:上文中说的常量constant是不可以被装潢的。

 

posted @ 2015-10-26 11:00  亦风  阅读(210)  评论(0编辑  收藏  举报