Understanding Service Types
Last update: June 2014. I have partially rewritten this article to provide more technical details and also to show their differences more clearly.
Angular comes with different types of services. Each one with its own use cases.
Something important that you have to keep in mind is that the services are always singleton, it doesn’t matter which type you use. This is the desired behavior.
NOTE: A singleton is a design pattern that restricts the instantiation of a class to just one object. Every place where we inject our service, will use the same instance.
Provider
Provider
is the parent of almost all the other services (all but constant) and it is also the most complex but more configurable one.
Let’s see a basic example:
1 |
|
A provider
on its simplest form, just needs to return a function called $get
which is what we inject on the other components. So if we have a controller and we want to inject this foo
provider, what we inject is the $get
function of it.
Why should we use a provider
when a factory
is much simple? Because we can configure a provider
in the config function. We can do something like this:
1 |
|
Here we moved the thisIsPrivate
outside our $get
function and then we created a setPrivate
function to be able to change thisIsPrivate
in a config function. Why do we need to do this? Won’t it be easier to just add the setter in the $get
? This has a different purpose.
Imagine we want to create a generic library to manage our models and make some REST petitions. If we hardcode the endpoints URLs, we are not making it any generic, so the idea is to be able to configure those URLs and to do so, we create a provider and we allow those URLs to be configured on a config function.
Notice that we have to put nameProvider
instead of just name
in our config function. To consume it, we just need to use name
.
Seeing this we realize that we already configured some services in our applications, like $routeProvider
and $locationProvider
, to configure our routes and html5mode respectively.
Providers
have two different places to make injections, on the provider constructor and on the $get
function. On the provider constructor we can only inject other providers and constants (is the same limitation as the config
function). On the $get
function we can inject all but other providers (but we can inject other provider’s $get
function).
Remember: To inject a provider you use: name + ‘Provider’ and to inject its $get
function you just use name
Try it
Factory
Provider
are good, they are quite flexible and complex. But what if we only want its $get
function? I mean, no configuration at all. Well, in that cases we have the factory
. Let’s see an example:
Example:
1 |
|
As you see, we moved our provider
$get
function into a factory
so we have what we had on the first provider
example but with a much simpler syntax. In fact, internally a factory
is a provider
with only the $get
function.
As I said before, all types are singleton, so if we modify foo.variable
in one place, the other places will have that change too.
We can inject everything but providers on a factory
and we can inject it everywhere except on the provider
constructor and config functions.
Try it
Value
Factory
is good, but what if I just want to store a simple value? I mean, no injections, just a simple value or object. Well angular has you covered with the value
service:
Example:
1 |
|
Internally a value
is just a factory. And since it is a factory
the same injection rules applies, AKA can’t be injected into provider
constructor or config functions.
Try it
Service
So having the complex provider
, the more simple factory
and the value
services, what is the service
service? Let’s see an example first:
Example:
1 |
|
The service
service works much the same as the factory
one. The difference is simple: The factory
receives a function that gets called when we create it and the service
receives a constructor function where we do a new
on it (actually internally is uses Object.create
instead of new
).
In fact, it is the same thing as doing this:
1 |
|
Foobar
is a constructor function and we instantiate it in our factory
when angular processes it for the first time and then it returns it. Like the service, Foobar
will be instantiated only once and the next time we use the factory
it will return the same instance again.
If we already have the class and we want to use it in our service
we can do that like the following:
1 |
|
If you’re wondering, what we did on foo2
is actually what angular does with services internally. That means that service
is actually a factory
and because of that, same injection rules applies.
Try it
Constant
Then, you’re expecting me to say that a constant
is another subtype of provider
like the others, but this one is not. A constant
works much the same as a value
as we can see here:
Example:
1 |
|
So… what’s the difference then? A constant
can be injected everywhere and that includes provider
constructor and config functions. That is why we use constant
services to create default configuration for directives, because we can modify those configuration on our config functions.
You are wondering why it is called constant
if we can modify it and well that was a design decision and I have no idea about the reasons behind it.
Try it
Bonus 1: Decorator
So you decided that the foo
service I sent to you lacks a greet
function and you want it. Will you modify the factory
? No! You can decorate it:
1 |
|
$provide
is what Angular uses internally to create all the services. We can use it to create new services if we want but also to decorate existing services. $provide
has a method called decorator
that allows us to do that. decorator
receives the name of the service and a callback function that receives a $delegate
parameter. That $delegate
parameter is our original service instance.
Here we can do what we want to decorate our service. In our case, we added a greet
function to our original service. Then we return the new modified service.
Now when we consume it, it will have the new greet
function as you will see in the Try it
.
The ability to decorate services comes in handy when we are consuming 3rd party services and we want to decorate it without having to copy it in our project and then doing there the modifications.
Note: The constant
service cannot be decorated.
Try it
Bonus 2: Creating new instances
Our services are singleton but we can create a singleton factory that creates new instances. Before you dive deeper, keep in mind that having singleton services is the way to go and we don’t want to change that. Said that, in the rare cases you need to generate new instances, you can do that like this:
1 |
|
Here we create a Person
object which receives some json to initialize the object. Then we created a function in our prototype (functions in the prototype are for the instances of the Person
) and a function directly in Person
(which is like a class function).
So we have a class function that will create a new Person
object based on the id that we provide (well, it will in real code) and every instance is able to update itself. Now we just need to create a service that will use it.
Every time we call personService.getById
we are creating a new Person
object, so you can use this service in different controllers and even when the factory in a singleton, it generates new objects.
Kudos to Josh David Miller for his example.
Try it
Bonus 3: Coffeescript
Coffeescript can be handy with services since they provide a prettier way to create classes. Let’s see an example of the Bonus 2
using Coffeescript:
1 |
|
It is prettier now in my humble opinion.
Try it
NOTE: This last one, being Coffeescript seems to fail a little bit with JSbin. Go to the Javascript tab and select Coffeescript to make it work.
Conclusion
Services are one of the coolest features of Angular. We have a lot of ways to create them, we just need to pick the correct one for our use cases and implement it.
If you found any issue or you think that this can be improved, please leave an issue or pull request at Github. In any case, a comment will be appreciated :).
http://angular-tips.com/blog/2013/08/understanding-service-types/
Understanding Service Types的更多相关文章
- 浅析Kubernrtes服务类型(Service Types)
先上图 在Kubernetes集群中,service通过标签选择器选着对应的pod,然后对请求进行转发,看个动画,能直接了当体会到便签选择器 pod,endpoints,service三者关系 1.举 ...
- Learning WCF Chapter1 Generating a Service and Client Proxy
In the previous lab,you created a service and client from scratch without leveraging the tools avail ...
- Learning WCF Chapter1 Exposing Multiple Service Endpoints
So far in this chapter,I have shown you different ways to create services,how to expose a service en ...
- Service Fabric Cluster Manager
作者:潘罡 (Van Pan)@ Microsoft 我们回到Service Fabric最底层的话题,谈谈Service Fabric是怎么工作的. 首先,我们回到下面的文档,看看Service F ...
- service fabric docker 安装
1. 镜像拉取 docker pull microsoft/service-fabric-onebox 2. 配置docker(daemon.json) { "ipv6": tru ...
- F#之旅2 - 我有特别的学F#技巧
原文地址:https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/learning-fsharp/ Learning F#Functio ...
- WCF服务与WCF数据服务的区别
问: Hi, I am newbie to wcf programming and a little bit confused between WCF Service and WCF Data Se ...
- wcf中的File-less Activation
File-less Activation Although .svc files make it easy to expose WCF services, an even easier approac ...
- Eclipse MAT: Understand Incoming and Outgoing References
引用:http://xmlandmore.blogspot.hk/2014/01/eclipse-mat-understand-incoming-and.html?utm_source=tuicool ...
随机推荐
- Oracle 11g 客户端 下载地址
摘自: http://blog.csdn.net/davidhsing/article/details/8271845 Oracle Database Instant Client 11g 11.2. ...
- EnCase v7 could not recognize Chinese character folder names / file names on Linux Platform
Last week my friend brought me an evidence file duplicated from a Linux server, which distribution i ...
- 网站屏蔽指定ip
修改.htaccess文件 Order Deny,Allow //开启屏蔽Deny from 124.64.242.117 //要屏蔽的ip
- nginx负载均衡配置一(反向代理)
一.前提 1:系统linux(centos) 2:nginx代理服务器(web:192.168.1.10 proxy.abc.com) 3:nginx后台服务器(web1:192.168.1.11 ...
- 第 2章 数组和 ArrayLists
数组是最通用的数据结构,它出现在几乎所有的编程语言里.在 C#语言中使用数组包括创建 System.Array 类型的数组对象,以及创建针对所有数组的抽象的基类型.Array 类提供了一套方法,这些方 ...
- php去除换行(回车换行)的方法
php去除换行(回车换行)的三种方法. 代码: <?php //php 不同系统的换行 //不同系统之间换行的实现是不一样的 //linux 与unix中用 \n //MAC ...
- 升级Mac X Mavericks MacMiv 无法启动
今天把Mac 系统升级到了 Mac X Mavericks ,确实有不少的惊喜.虽然体验不出Mac X Mavericks拥有更强的性能/更好的电池表现,但是新版的Safari浏览器的提供了更方便的主 ...
- 主键、外键、超键、候选键的区别【Written By KillerLegend】
先说一下属性的定义: 表的每一行对应一个元组,表的每一列对应一个域.由于域可以相同,为了加以区分,必须对每列起一个唯一的名字,称为属性(Attribute). 再来看看几个键的定义: 超键:在关系模式 ...
- Delphi 7 里没有加载的控件
在原来版本如D5.D6中使用的控件如Quickrep,FastNet等,在D7中仍然是保留的.只是Delphi没有将他们默认的安装到组件面版中来.这些控件包全部保存在Delphi目录的bin下,文件扩 ...
- Python核心编程--学习笔记--4--Python对象
现在开始学习Python语言的核心部分.首先了解什么是Python对象,然后讨论最常用的内建类型,接下来讨论标准类型运算符和内建函数,之后给出对标准类型的不同分类方式,最后提一提Python目前还不支 ...