当前位置: 首页 > news >正文

Angular.js Services

      Angular带来了很多类型的services。每个都会它自己不同的使用场景。我们将在本节来阐述。

   首先我们必须记在心里的是所有的services都是singleton(单例)的,这也是我们所希望得到的预期结果。

下面让我开始今天的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 servicefactory工作原理一样,只是他service接收的是一个构造函数,当第一次使用service的时候,angularnew 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的函数,其返回值将会被注入其他应用组件。所以我们注入foocontroller,我们注入的是$get 函数。

为什么我们还需要providerfactory实现不是更简单吗?这是因为我们能够在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的资源resourceservice,我们希望能够配置是从那个url获取资源,我们也将有个三方的消费者比如restangular允许我们去配置达到我们的目的。

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

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

额外的福利:

福利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;

});

});
复制代码

 

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

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

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

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

福利2:创建非单例对象

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

复制代码
// Our class

function Person( json ) {

angular.extend(this, json);

}



Person.prototype = {

update: function() {

// Update it (With real code :P)

this.name = "Dave";

this.country = "Canada";

}

};



Person.getById = function( id ) {

// Do something to fetch a Person by the id

return new Person({

name: "Jesus",

country: "Spain"

});

};



// Our factory

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

return {

getById: Person.getById

};

});
复制代码

 

     在这里我们创建了一个Person对象,它几首一些json对象来初始化对象。接下来我们在prototype中创建了一个函数(可以从面向对象语言理解为实例方法),在我们直接在Person类上加了一个方法(可以理解为类方法,静态方法)

   所以我们有一个类方法将根据我们提供的id创建一个新的person对象,并每隔实例可以更新自己。接下来我们只需要创建一个service去消费它。

   在任何时候我们调用personService.getByID,我们都会创建一个新的person对象,所以在不同的controller中你可以使用一份新的person对象,即使factory是单例的,但是它生产返回的却是新的object

福利3CoffeeScript

   CoffeeScrip能够方便优雅的处理service,提供的优雅的方式去创建class。下面是福利2的示例用CoffeeScript改变后的:

复制代码
app.controller 'MainCtrl', ($scope, personService) ->

$scope.aPerson = personService.getById(1)



app.controller 'SecondCtrl', ($scope, personService) ->

$scope.aPerson = personService.getById(2)

$scope.updateIt = () ->

$scope.aPerson.update()



class Person



constructor: (json) ->

angular.extend @, json



update: () ->

@name = "Dave"

@country = "Canada"



@getById: (id) ->

new Person

name: "Jesus"

country: "Spain"



app.factory 'personService', () ->

{

getById: Person.getById

}
复制代码

 

     译者注:本人一直在思考一篇《为什么需要在你的项目中尝试CoffeeScript.CoffeeScript不仅仅优美语法,如果只是这样的话,充其量这也只是一些可有可无的语法糖而已,我们认为更重要的是它为我们写javascript带来了一些好的实践,规避了javascript的“坑”.但是也不得不考虑项目成员学习成本,如果你项目成员很多具有函数式编程的经历,javascript能力也不错,你完全可以去尝试。注:写CoffeeScript并不是说你不再需要javascript学习。

总结:

    serviceangularjs另一个非常酷的features。我们有许多方式去创建service,我们需要根据我们的应用场景选择正确的方式去实现它。译者注:这就好比我们常挂在嘴边的设计模式,重要的是正确的场景使用正确的模式。

本来原文来自:http://angular-tips.com/blog/2013/08/understanding-service-types/

 


作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客、博客园--破狼和51CTO--破狼。http://www.cnblogs.com/whitewolf/p/angular-services.html


相关文章:

  • 折腾Openoffice---解决中文和注册问题(原创)
  • react 入门到放弃 之 webpack
  • 如何用Beyond Compare对比压缩文件
  • iOS推送通知的实现步骤
  • 异步与并行~大话目录
  • MySQL in不走索引
  • linu系统管理中和shell编程中常用的技巧
  • 云栖社区
  • linux下升级python版本
  • CentOS 7 网络配置
  • Report Server Windows Service (MSSQLSERVER) 无法与报表服务器数据库建立连接 错误ID107...
  • 滴滴算法大赛算法解决过程 - 机器学习
  • 构建之法阅读笔记4
  • 提高PHP网站安全性5个技巧
  • Unity中双击 / 单击事件
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • Android单元测试 - 几个重要问题
  • Android系统模拟器绘制实现概述
  • crontab执行失败的多种原因
  • gcc介绍及安装
  • OSS Web直传 (文件图片)
  • PaddlePaddle-GitHub的正确打开姿势
  • Redis 中的布隆过滤器
  • 编写符合Python风格的对象
  • 成为一名优秀的Developer的书单
  • 观察者模式实现非直接耦合
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用API自动生成工具优化前端工作流
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 延迟脚本的方式
  • elasticsearch-head插件安装
  • 阿里云重庆大学大数据训练营落地分享
  • ​queue --- 一个同步的队列类​
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (2020)Java后端开发----(面试题和笔试题)
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (三)elasticsearch 源码之启动流程分析
  • (四)c52学习之旅-流水LED灯
  • (转)大型网站的系统架构
  • (转)用.Net的File控件上传文件的解决方案
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net web项目 调用webService
  • .NET 设计模式初探
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET性能优化(文摘)
  • .php文件都打不开,打不开php文件怎么办
  • .sdf和.msp文件读取
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [2]十道算法题【Java实现】