[转载]AngularJS之Factory vs Service vs Provider

http://www.oschina.net/translate/angularjs-factory-vs-service-vs-provider

http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/

要注意的文章中,app.provider(...)里的代码有点出处,之后作者改过,但是转载的网站上图片上没有改掉,应该是

 //Going to set this property on the config function belowthis.thingFromConfig = '';

-------------------------------------------------------

当你初试 Angular 时,很自然地就会往 controller 和 scope 里堆满不必要的逻辑。一定要早点意识到,controller 这一层应该很薄;也就是说,应用里大部分的业务逻辑和持久化数据都应该放在 service 里。我每天都会在 Stack Overflow 上看到几个同类的问题,关于如何在 controller 里保存持久化数据。这就不是 controller 该干的事。出于内存性能的考虑,controller 只在需要的时候才会初始化,一旦不需要就会被抛弃。因此,每次当你切换或刷新页面的时候,Angular 会清空当前的 controller。与此同时,service 可以用来永久保存应用的数据,并且这些数据可以在不同的 controller 之间使用。

Angular 提供了3种方法来创建并注册我们自己的 service。

  1. Factory

  2. Service

  3. Provider

如果你是“太长的不看”

1) 用  Factory 就是创建一个对象,为它添加属性,然后把这个对象返回出来。你把 service 传进 controller 之后,在 controller 里这个对象里的属性就可以通过 factory 使用了。

FactoryExample1

2) Service  是用"new"关键字实例化的。因此,你应该给"this"添加属性,然后 service 返回"this"。你把 service 传进 controller 之后,在controller里 "this" 上的属性就可以通过 service 来使用了。

ServiceExample2

3) Providers  是唯一一种你可以传进 .config() 函数的 service。当你想要在 service 对象启用之前,先进行模块范围的配置,那就应该用 provider。

ProviderExample3

详细解释(对于不是“太长不看”的读者)

为了准确表现出 Factory、Service 和 Provider 之间的差别,下面我们用 3 种不同的方式来构建同一个服务。这个服务会用到 iTunes API 以及使用 $q 的 promise。

1) Factory

Factory 是创建和配置服务最常见的方式。除了“快速浏览”之外,其实没有什么要补充的。只需创建一个对象,为它添加属性,然后返回这个对象就可以了。当你把 factory 传进 controller 中,对象的这些属性就可以通过 factory 访问。更详细的例子如下:

首先创建一个对象,然后返回这个对象,如下。

factory1-4

现在如果我们把"myFactory"传进 controller 里,附加在 "service" 上的任何属性都可以访问到了。

现在让我们向回调函数中添加一些“private” 变量。当然 controller中是无法直接访问这些变量的,不过我们最终还是会在“service”中设置setter和个getter 方法,以便必要时修改这些“private”变量。

factory4-5

你可能注意到了,我们没有将变量/函数加到“service”中。我们只是简单的创建他们以便之后的使用和修改。

  •  baseUrl 是iTunes API要求的根URL

  •  _artist 是我们想要查找的艺术家

  • _finalUrl 是最终的权限定URL,即我们调用iTunes的入口

  • makeUrl 是一个创建并返回友好的iTunesURL的函数

既然我们的帮手/私有变量和函数放在的合适的位置,那么让我们向“service”对象中添加一些属性。无论我们向”service“中添加什么, 我们都能在任意一个我们传递进‘myFactory’ 的controller中使用。

我们来创建setArtist和getArtist方法来简单的返回或设置artist。同样创建一个方法使用我们创 建的URL来调用iTunes API。这个方法将返回一个从iTunes API获取数据后便会满足的promise。如果你对Angular的promise接触不多,我强烈推荐你深入的学习一下它。

  • setArtist 接受一个artist并且允许你设置artist

  • getArtist 返回artist

  • callItunes 首先调用makeUrl()方法以便构建$http请求使用的URL。然后它会设置promise对象,让$http请求我们最终的URL, 再然后呢,因为$http返回一个promise,所以我们可以在请求后调用.success或.error。最后我们可以通过iTunes的数据来解析 我们的promise,或者直接‘There was an error’来拒绝它。

factory6
 

现在我们的factory完成了。我们可以将"myFactory"注入到任意controller中了,然后就可以调用我们添加到service对象中的方法了(setArtist,getArtist,和callItunes)。

factory2-7

在上面的controller中,我们注入了‘myFactory’ service对象。然后我们设置$scope 对象的属性。上面唯一棘手的代码是处理promise。因为callItunes返回一个promise对象,一旦我们的promise满足了,我们可以 调用.then()方法以及设置$scope.data.artistData。你会注意到我们的controller是非常的“瘦”。因为我们所有的逻 辑和持久化数据都存放在了service中而不是controller中。

2) Service

当我们创建一个Service时,我们所知道的最重要事可能就是Service通过new关键字实例化对象。这应该可 以使熟悉JavaScript的人了解到了这段代码的作用。但对于那些JS背景有限,或者不太熟悉new关键字的作用的人来说可能有点困难。那就让我们来 重温一下JavaScript的基本功能,以便帮助我们了解Service究竟做了什么。

让我们先定义一个函数,然后通过new关键字来调用它,看看当解释器遇到了new关键字的时候做了些什么工作,以便帮助我们了解使用new关键字来实例化一个函数时究竟有什么变化。这个的最终结果应该和Service是一样的。

首先,让我们定义一个构造器。

personConstructor-8

这个一个典型的JavaScript式的构造方法。现在,只要我们使用new关键字来调用Person函数,就会将'this'关键字绑定到新创建的对象上。

接下来,让我们给Person的prototype对象添加一个方法,这个方法对所有Person ‘类’的实例都是可用的。

person.prototype-9

现在,由于我们往prototype上添加了一个sayName方法,所以所有的Person实例都可以调用这个方法,并且输出对应实例的name值。

既然我们已经有了一个Person的构造器,并在在其prototype上定义了一个sayName方法,那就让我们去创建一个Person的实例,并调用这个sayName方法。

personInstance-10

接下来,我们把创建Person构造器、往其prototype上添加方法、创建一个Person实例,并调用sayName方法的代码写在一块,如下所示:

PersonCode-11

现在,让我们看一下当我们在JavaScript中使用new关键字的时候究竟发生了什么。首先你应该已经注意到的 是,当我们在例子中使用了new关键字之后,我们可以通过'tyler'来调用方法(sayName),看上去好像tyler是一个对象——那是因为它确 实成了一个对象。所以,我们知道的第一件事就是我们的Person构造器返回了一个对象(object)。其次,我们知道,由于我们的sayName方法 是定义在Person的prototype上,而不是直接定义在Person的实例上的,所以Person函数返回的对象(tyler)一定是由于未找到 sayName方法,进而去prototype寻找sayName方法的。用更通俗的话来说,当我们调用tyler.sayName()时,JS解释器 说,“好吧,我先去我们刚创建的'tyler'对象上查找sayName方法,然后调用它。等一下,我没有在它上面找到sayName方法——我只看到了 name和age,那让我去prototype找一下吧。没错,它在prototype上,那就让我调用它吧”。

下面的代码演示了在JavaScript中使用new关键之后所做的事。它是上面这一段文字的一个基本的代码示例。我已经把从JS解释器的角度来看整个过程的代码写在了注释里。

PersonCommented-12

现在,既然我们了解了在JavaScript中new关键字是如何工作的,那么在Angular中创建一个Service也应该变得容易理解了。

在创建一个Service时,需要理解的最重要的一件事就是我们使用new关键字去实例化Service对象。结合我 们从上面的例子所了解到的知识,你应该已经意识到你可以将一些属性和方法直接添加到this上,之后,在创建Service对象时,this会被作为返回 值返回。让我们来看一下这种工作方式。

我们不用像之前Factory中的例子那样创建一个对象,然后返回这个对象。因为我们使用了new关键字来调用,解释器会创建一个对象,并关联它的prototype对象,然后将该对象返回,而不用我们去做这些工作。

首先,让我们创建我们的私有辅助函数。它应该看起来和我们在factory中所作的工作很类似。由于我已经在factory的例子中解释过每一行代码的含义了,所以我不会在这里多作解释,如有疑惑,请再次回味一下factory的例子。

ServiceBase-13

接下来,我们将要把可以从控制器中访问的方法添加到‘this’上。

serviceservice-14

现在,和使用factory一样,所有将myService作为参数传入的控制器都可以访问到setArtist, getArtist, 和callItunes方法。下面是传入了myService的控制器(基本上和factory的控制器一样)。
ServiceController-15

正如我之前提到的那样,一旦你了解了new关键字的作用,你就会知道在Angular中,Services和Factories几乎一样。

3) Provider

要记住的关于Provider的最重要的事情是,它们是你可以传递到应用程序的app.config部分唯一的服务。 如果你需要在你的服务对象可以在你的应用程序之外任何地方都可用之前改变它的某些部分,这是非常重要的。虽然Services/Factories很相 似,但也有一些差异,我们将会讨论它们。

首先,我们用与我们建立Service 和 Factory类似的方式来建立我们的Provider。下面的变量是我们的'私人'和辅助功能。

ProviderBase-16

*同样地,如果上面的代码的任何部分令你纠结,请看下 Factory 部分,在那里我更详细地解释了这些代码的作用。

必须要注意的一点是只有这些变量和函数是可以在我们的app.config函数中访问的。这曾一度使我感到困惑,所以 你最好也要知道这点不同之处。你可以把Provider想象成由两部分组成。第一部分的变量和函数是可以在app.config函数中访问的,因此你可以 在它们被其他地方访问到之前来修改它们(如上所示)。第二部分(如下所示) 的变量和函数是可以在任何传入了’myProvider‘的控制器中进行访问 的。

当你使用Provider创建一个service时,唯一的可以在你的控制器中访问的属性和方法是通过$get()函 数返回内容。下面的代码将$get方法写在了’this‘(最终会被函数返回)上。现在,$get函数会返回所有我们希望在控制器中进行访问的方法和属 性。下面是代码示例:

provider$get-17

现在,Provider的完整代码如下所示:

ProviderService-18

现在,与我们的Factory和Service类似,setArtist, getArtist, 和callItunes可以在任何一个传入了 myProvider 的控制器中访问。下面是myProvider的控制器(几乎和我们Factory/Service中的控制器一样)。

ProviderCtrl-19

正如前面提到的那样,使用Provider创建一个service的独特之处是,你可以在Provider对象传递到应用程序的其他部分之前在app.config函数对其进行修改。让我们来看一个对应的例子。

appconfig-20

现在你可以明白‘thingFromConfig’是怎么样地在我们的provider中是空字符串,而当它出现在DOM中时,它将是'This sentence was set…’。

谢谢您的阅读,我希望这有助于你能辨别在Angular中Factory, Service, 和 Provider之间的差异。

*要查看完整的代码示例,看看运行中的代码,可以自由地fork我的repo: https://github.com/tylermcginnis33/AngularService

转载于:https://www.cnblogs.com/Benoly/p/4246209.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#学习笔记:预处理指令

C#和C/C一样,也支持预处理指令,下面我们来看看C#中的预处理指令。 #region 代码折叠功能,配合#endregion使用,如下: 点击后如下: 条件预处理 条件预处理可以根据给出的条件决定最终进行编译的代码&#xff…

【数字信号处理】 第二章、时域中的离散时间信号

前言 学而时习之,不亦乐乎? ——《论语学而》 Is it not pleasant to learn with a constant perseverance and application? 。 第二章 时域中的离散时间信号 一、离散信号的基本定义 1、两个基本类型 抽样数据类型:即模拟信号通过定周期进行采样…

开机流程与主引导分区(MBR)——鸟哥私房菜

在前篇随笔中,已经谈到了CMOS与BIOS,CMOS是记录各项硬件参数(包括系统时间、设备的I/O地址、CPU的电压和频率等)且嵌入到主板上面的存储器,BIOS是一个写入到主板上的韧体(韧体是写入到硬件上的一个软件程序…

ch12 GUI

《Head First Java 2nd Edition》 摘录 JFrame 代表屏幕上的一个窗口,可以把 buttons, checkboxes, test fields 等等界面相关的东西置于其上。它可以有一个有菜单项的菜单条。无论在哪个平台上,都有窗口图标,最小化、最大化和关闭窗口的按钮…

ARM寄存器

ARM处理器模式 用户模式(User):ARM处理器正常的程序执行状态 快速中断模式(FIQ):用于高速数据传输或通道处理 外部中断模式(IRQ):用于通用的中断处理 管理模式(Supervisor):操作系统使用的保护模式 数据访问终止模式(Abort):当数据或指令预取终止时进入该模式,可用于虚拟存储及…

修改shape数据 小数位数_【数据管理】Excel实用精华

点击上方蓝字关注星标★不迷路来源:从Excel小白到数据分析师这是一篇关于Excel中的小技巧但是都是精华,文中附有操作视屏简单易学上手快噢!01添加数据有效性_名称管理器数据有效性是对单元格或单元格区域输入的数据从内容到数量上的限制。对于…

ICMP:Internet控制报文协议

ICMP:Internet控制报文协议。是IP层的组成部分。传递差错报文或其他信息。 ICMP报文被封装在IP数据报内部:详细格式例如以下所看到的:个字段含义例如以下:8位类型。表示该ICMP报文的含义,如目的不可达、超时、请求回显…

分离圆环图显示百分比_Tableau制作圆环图

Tableau圆环图制作 声明:本文内容来源拉勾教育数据分析训练营, 封面图片来源pexels网站圆环图制作过程如下:建立饼图2. 设置记录平均值3. 在第二个字段的下拉菜单中选择双轴4. 点击右侧坐标轴,右键选择同步轴(同步轴指…

FLEX 布局

网页布局(layout)是CSS的一个重点应用。 布局的传统解决方案,基于盒状模型,依赖 display属性 position属性 float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3…

SpiderMonkey-让你的C++程序支持JavaScript脚本

译序 有些网友对为什么D2JSP能执行JavaScript脚本程序感到奇怪,因此我翻译了这篇文章,原文在这里。这篇教程手把手教你怎样利用SpiderMonkey创建一个能执行JavaScript脚本的C程序,并让JavaScript脚本操纵你的C程序的内部数据、操作。从这篇教…

MobX快速入门教程(重要概念讲解)

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7372119.html 一:Mobx工作流程图 二:MobX涉及到的概念 1:状态state 组件中的数据。 2:被观察observable 被observable修饰的state数据将会暴露给整个app,各观察者组件都可以…

循环结束后变回去 设置一个值_VBA掌握循环结构,包你效率提高500倍

这是系列免费教程《Excel VBA:办公自动化》,还是老规矩,看看我们走到哪里了。1.认识VBA:什么是VBA?2.这些掌握了,你才敢说自己懂VBA3.VBA变量5年踩坑吐血精华总结4.VBA中重要的强制申明,谁看谁明…

连接到kali linux服务器上的MySQL服务器错误

前言:想把数据库什么的都放在虚拟机kali Linux里,但无奈出了好多错误。 首先:可以参照上一篇文章开启kali服务器端的远程连接功能,上一篇文章 然后:使用window端的sqlyog(MySQL图形化连接工具)连…

dedecms后台怎么添加发布软件?织梦后台软件内容管理

使用织梦cms有很多的功能,其中有一个是在dedecms后台添加发布软件,然后在前台大家可以直接下载软件,在织梦cms后台怎么添加发布软件呢?下面是织梦软件内容管理的主要操作步骤。使用织梦cms有很多的功能,其中有一个是在…

301 302区别_如何正确理解301,302和canonial标签

今天我们来学习一下几个比较容易混淆的页面跳转标签,301,302,relcanonial。在谷歌SEO里面,我们比较容易常见的是第一个301,302和canonial出现的比较少,但是不代表不存在,我会尝试从以下价格方面…

为什么手机游戏手柄没有流行起来?

问答社区知乎上有人提了一个问题,“为什么手机用游戏手柄没有流行?” Ta找了不少论证:1)手机用户数量很大;2)大量用户在手机上花费最多时间的是玩游戏;3)游戏机平台(的游…

c++排序算法ppt_C/C++学习教程:C语言排序算法—插入排序算法

前言:插入排序算法是所有排序方法中最简单的一种算法,其主要的实现思想是将数据按照一定的顺序一个一个的插入到有序的表中,最终得到的序列就是已经排序好的数据。直接插入排序是插入排序算法中的一种,采用的方法是:在…

python函数参数

1.位置参数 2.默认参数 指向参数为不可变对象 3.可变参数 **args 一个列表list或是元组tuple 4.关键字参数 **kw,是一个字典dict 5.命名关键字参数 *, 转载于:https://www.cnblogs.com/aliy-pan/p/5198025.html

Python 常用函数 configparser模块

使用ConfigParser模块读写ini文件 ConfigParserPython的ConfigParser Module中定义了3个类对INI文件进行操作。分别是RawConfigParser、ConfigParser、SafeConfigParser。模块所解析的ini配置文件是由多个section构成,每个section名用中括号‘[]’包含,每…

自制Unity小游戏TankHero-2D(3)开始玩起来

自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的。仅为学习Unity之用。图片大部分是自己画的,少数是从网上搜来的。您可以到我的github页…