常见的后端开发中,有个MVC开发模式:Model-View-Controller。在MVC架构中,有个service层,负责是连接Controller和Model。Controller处理用户的输入和请求,Service负责从Model中获取数据并处理数据,Model定义数据库的字段定义和一些行为。在Angular中,Service作为一个服务,和MVC中的Service相类似,但是还是有差别的。
说起Angular,不得不说下MVVM设计模式:Model-View-ViewModel。
- Model数据层,它是与应用程序的业务逻辑相关的数据的封装载体,在web页面中,大部分Model都是来自请求的服务端返回单数据或者是全局配置的对象。Angular中service则是封装和处理这些Model相关的业务逻辑的所在。
 - View视图,声明式模板,专注于界面的显示和渲染。
 - ViewModel视图-数据,它是View和Model的黏合体,负责View和Model的交互和协作。利用框架内置的双向绑定技术来实现View和Model的粘合。
 
为什么我们需要Service?
Angular的service是一个简单的TypeScript类,它封装了一些用于完成应用程序中特定任务的方法,例如从服务器获取数据或者向服务器发送数据。
Angular Service 具有以下的作用:
- 用来将应用程序中的业务逻辑组件中的渲染逻辑分离
 - 用来在Angular应用中的多个组件之间共享数据
 - 让程序易于测试和调试
 - 用于编写可重用的代码。
 
创建一个Service
声明一个Service,需要使用Angular Core包提供的@Injectable装饰器,这意味着该服务可以被注入到组件和其他服务中。
我们可以使用Angular cli命令行创建一个服务:
1  | ng g s auth  | 
这样就创建了一个文件名为:auth.server.ts文件,里面有一个类:AuthService,看看里面具体的内容:
1  | import {Injectable} from '@Angular/core';  | 
Injectable元数据提供了一个providedIn属性告诉Angular 注入器我们这个类的作用域以及他可以被注入到哪里。
@Injectable为标记性元数据,表示一个类可以由Injector创建。可以接受的选项有providedIn,这个参数描述了这个类的注入等级。providedIn接受的值有:
root将服务注入到根组件中,这样它是全局共享的一个单例服务。platform页面所有应用程序共享的特殊单例平台注入器。any可以是任何Angular Module
Service可以被注入到root或者其他任何可用Module(使用any或直接使用Module)。any是Angular9版本开始支持。
我们可以给这个服务增加一个方法,从服务器中获取用户数据。
为了发送Http请求,我们需要导入HttpClientModule来注入HttpClient服务,我们需要src/app.component.ts中的import数组中添加HttpClientModule:
1  | import {BrowserModule} from '@angular/platform-browser';  | 
HttpClient也是一个服务,我们可以将它注入到我们的AuthService中:
1  | import {Injectable} from '@angular/core';  | 
服务提供商配置注入器
我们前面创建的类提供了一个服务,@Injectable装饰器把它标记为可注入的服务。但是在我们使用服务的provider提供商配置好Angular依赖注入器之前,Angular无法将其注入到任何位置。
前面我们创建的服务:AuthService,为什么我们没有配置provider注入器,但是可以在组件中使用呢?
是因为在创建的时候默认将providedIn配置为root,这就创建了一个当前应用程序全局的服务。我们可以在任何组件里面使用,而不用特意在组件或模块中声明provider。
可以在以下三种位置之一设置元数据,以便在应用的不同层级使用提供商来配置注入器:
- 服务本身的
@Injectable装饰器providedIn元数据中设置。 - 在
NgModule的@NgModule装饰器providers元数据中设置,模块级的注入器。 - 在组件的
@Component装饰器providers元数据中设置,组件级的注入器。 
所有的组件都是指令,而providers选项是从@Directive中继承来的,所以也可以与组件一样的级别为指令、管道配置服务提供商。
注入一个Service
先来了解下DI(Dependency Injection 依赖注入),DI是一种编码模式,一个类请求从外部资源中提供依赖关系,而不是去自己创建它们。
注入服务意味着什么?
Angular使用Dependency Injection(依赖注入,DI)来提供Service的实例给组件或者其他服务,这意味我们在使用这个服务之前无需手动去创建它;我们只需要告诉依赖注入(DI)我们需要使用这个服务,这样依赖注入会给我们提供这个服务的实例。那么我们如何告诉DI我们需要使用这个服务?
我们仅需要在组件或服务的构造函数中定义需要注入的服务,通过带有依赖类型的构造函数参数来要求Angular在组件的构造函数中注入依赖项。
我们在AppComponent中使用AuthService:
1  | import {Component, OnInit} from '@angular/core';  | 
可以看到,我们直接在组件中的constructor方法中声明我们需要的服务就可以使用这个服务,而不用创建这个服务。
这里我们了解了基本的Angular的Service的声明和注入,在使用上有全局的单例模式和模块或组件的注入模式。篇幅较长,服务的分级注入另写一篇。