框架依赖注入和普通依赖注入

服务和喷油器 (Services and Injectors)

Components are responsible for the data that renders into the template. Having external services to draw upon can simplify this responsibility. Plus, encapsulating extraneous is much easier to maintain.

组件负责渲染到模板中的数据。 利用外部服务可以简化此职责。 另外,封装无关的东西更容易维护。

Delegating too many responsibilities onto a single component can complicate the component class. And what if these responsibilities applied to several components? Copying and pasting such logic is extremely poor practice. Any future changes to the logic would be harder to implement and test.

将太多职责委派给单个组件可能会使组件类复杂化。 如果这些责任适用于几个组成部分怎么办? 复制和粘贴这种逻辑是极差的做法。 将来对逻辑所做的任何更改都将更难以实施和测试。

Angular meant to curb this issue with services and dependency injection. Both concepts work together to provide modular functionality.

Angular旨在通过服务和依赖注入来解决此问题。 这两个概念共同作用以提供模块化功能。

Components do not need to provide any extraneous information either. A services imports what it needs to function on behalf of the components it services. The components only need to instantiate the service. From there they service their own needs with the instantiated service instance.

组件也不需要提供任何无关的信息。 服务代表其服务的组件导入功能所需的内容。 组件仅需要实例化服务。 从那里,他们用服务实例化的服务实例自己的需要。

As for testing and future modification, all the logic is in one place. The service instantiates from its source. Tests and modifications to the source apply anywhere the service is injected.

至于测试和将来的修改,所有逻辑都放在一个地方。 该服务从其源实例化。 对源的测试和修改适用于注入服务的任何地方。

服务介绍 (Introduction to Services)

A service is a type of schematic available in Angular. It is generatable by the command-line interface (CLI): ng generate service [name-of-service]. Replace [name-of-service] with a preferable name. The CLI command yields the following.

服务是Angular中可用的一种示意图 。 它可以通过命令行界面(CLI) ng generate service [name-of-service]ng generate service [name-of-service] 。 将[name-of-service]名称[name-of-service]替换为首选名称。 CLI命令产生以下内容。

import { Injectable } from '@angular/core';@Injectable({providedIn: 'root'
})
export class LoggerService {constructor() { }
}

The logic of a service is distinct within its class. Angular interprets a class as an injectable service based off the @Injectable decorator. Injectable services must register with an injector.

服务的逻辑在其类中是不同的。 Angular基于@Injectable装饰器将类解释为可注入服务。 注射服务必须在注射器上注册

The component instantiates a service while the injector provides that instance. Keep reading into the next section for more on injectors.

当注入器提供该实例时,该组件实例化服务。 请继续阅读下一部分,以获取有关喷油器的更多信息。

The @Injectable metadata field providedIn: ‘root’ targets the root module of the current application (app.module.ts). It registers the service with the module’s injector so that it can inject that service into any of its children.

@Injectable元数据字段@Injectable providedIn: 'root'用于当前应用程序的根模块( app.module.ts )。 它注册到模块的喷油器的服务,以便它可以注入该服务到任何孩子。

Injectors are the building blocks of Angular’s dependency injection system. Injectors are a good place to focus your attention before continuing with services.

注入器是Angular依赖注入系统的基础。 在继续进行服务之前,喷油器是集中您注意力的好地方。

喷油器 (Injectors)

An application, beginning with app.module.ts, contains a hierarchy of injectors. They exist alongside each module and component in the application tree.

app.module.ts开头的应用程序包含注射器的层次结构。 它们与应用程序树中的每个模块和组件并存。

The green circles indicate injectors. They provide service instances to instantiating components. Depending on which injector a service is registered with, it may or may not be available to a component.

绿色圆圈表示喷射器。 它们提供服务实例来实例化组件。 根据向其注册服务的喷射器,组件可能会或可能无法使用该服务。

Services registered at the root of the app (app.module.ts) are available to all components. An injector for a component may not have a certain service registered. If that is the case and the component requests its instantiation, the injector will defer to its parent. This trend continues until either reaching the root injector or the service is found.

在应用程序的根目录( app.module.ts )注册的服务可用于所有组件。 组件的注射器可能未注册某些服务。 如果是这种情况,并且组件请求其实例化,则注入器将延迟其父对象。 这种趋势一直持续到到达根注入器或找到服务为止。

Looking at the diagram, say that a service registers at point B’s injector. All components at point C and down will not be able to access the service registered at B’s injector. Injectors will never defer to their children for a service instance.

查看该图,假设某个服务在B点的注入器处注册。 C点及以后的所有组件将无法访问在B的喷油器处注册的服务。 注入器永远不会服从其子实例进行服务。

依赖注入 (Dependency Injection)

There are multiple ways to register a service with an application’s injectors.

有多种向应用程序的注入器注册服务的方法。

The providedIn: ‘root’ metadata field of @Injectable provides the most recommended approach. This metadata field released with Angular 6.

@Injectable providedIn: 'root'元数据字段提供了最推荐的方法。 该元数据字段随Angular 6一起发布。

As mentioned before, providedIn: ‘root’ registers a service with the root module injector. It is instantiable across the entire application as a result.

如前所述, providedIn: 'root'向根模块注入器注册服务。 结果,它可在整个应用程序中实例化。

The novelty of providedIn: ‘root’ is tree-shaking. If the service is unused despite its registration, it gets shaken from the application at run-time. That way it does not consume any resources.

ProvideIn的新颖之处在于providedIn: 'root'令人震惊 。 如果该服务,尽管其注册未使用时,它会从在运行时应用动摇 。 这样,它不会消耗任何资源。

The other two ways are more direct and traditional. Granted, they do not offer tree-shaking.

其他两种方式更为直接和传统。 当然,它们不提供摇树。

A service can register with any injector along the component tree. You insert the service as a provider in the @Component metadata field: providers: []. The service is available to the component and its children

服务可以沿着组件树向任何注入器注册。 您将服务作为提供者插入@Component元数据字段中: providers: [] 。 该服务可用于组件及其子组件

In the third registration strategy, the providers: [] metadata exists as its own field in the @NgModule decorator. The service is instantiable from the module to the underlying component tree.

在第三个注册策略中, providers: []元数据作为其自己的字段存在于@NgModule装饰器中。 该服务可从模块实例化到基础组件树。

Remember that unlike with providedIn: ‘root’, @NgModule registration does not offer tree-shaking. Both strategies are otherwise identical. Once a service registers with @NgModule, it consumes resources even if left unused by the application.

请记住,与@NgModule providedIn: 'root'@NgModule注册不提供树状摇动。 两种策略在其他方面都是相同的。 服务使用@NgModule注册@NgModule ,即使应用程序未使用它,它也会消耗资源。

服务继续 (Services Continued)

Writing an actual service comes next. To recap, services handle certain functions on behalf of an application’s components.

接下来是编写实际服务。 概括地说,服务代表应用程序的组件处理某些功能。

Services excel at handling common operations. They spare components the responsibility by doing so. It saves time not having to re-write common operations across multiple components. It is also more testable because the code is in one place. Changes only need to happen in one place without having to search elsewhere.

服务擅长处理常见操作。 通过这样做,他们可以免除组件的责任。 它节省了不必在多个组件之间重写通用操作的时间。 由于代码位于一个位置,因此它也更具可测试性。 更改只需要在一个地方发生,而不必在其他地方进行搜索。

用例 (Use Cases)

A couple examples goes a long way towards a complete understanding of services.

几个示例对于全面理解服务大有帮助。

  • console logs控制台日志
  • API requestsAPI请求

Both are common across most applications. Having services to handle these operations will reduce component complexity.

两者在大多数应用程序中都很常见。 拥有处理这些操作的服务将降低组件的复杂性。

控制台日志 (Console Logs)

This example builds up from the base @Injectable skeleton. The skeleton is available through executing the CLI (ng generate service [name-of-service]]).

此示例从基础@Injectable骨架构建。 可通过执行CLI使用该框架( ng generate service [name-of-service]] )。

// services/logger.service.tsimport { Injectable } from '@angular/core';interface LogMessage {message:string;timestamp:Date;
}@Injectable({providedIn: 'root'
})
export class LoggerService {callStack:LogMessage[] = [];constructor() { }addLog(message:string):void {// prepend new log to bottom of stackthis.callStack = [{ message, timestamp: new Date() }].concat(this.callStack);}clear():void {// clear stackthis.callStack = [];}printHead():void {// print bottom of stackconsole.log(this.callStack[0] || null);}printLog():void {// print bottom to top of stack on screenthis.callStack.reverse().forEach((logMessage) => console.log(logMessage));}getLog():LogMessage[] {// return the entire log as an arrayreturn this.callStack.reverse();}
}

LoggerService registers with the root module through the @Injectable metadata. Thus it can instantiate in the app.component.html.

LoggerService通过@Injectable元数据向根模块注册。 因此,它可以在app.component.html实例化。

// app.component.tsimport { Component, OnInit } from '@angular/core';
import { LoggerService } from './services/logger.service';@Component({selector: 'app-root',templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {logs:object[] = [];constructor(private logger:LoggerService) { }updateLog():void {this.logger.printHead();this.logs = this.logger.getLog();}logMessage(event:any, message:string):void {event.preventDefault();this.logger.addLog(`Message: ${message}`);this.updateLog();}clearLog():void {this.logger.clear();this.logs = [];}ngOnInit():void {this.logger.addLog(“View Initialized”);this.updateLog();}
}

The template HTML provides further insight into the component’s use of LoggerService.

模板HTML可以进一步了解组件对LoggerService的使用。

<!-- app.component.html --><h1>Log Example</h1><form (submit)="logMessage($event, userInput.value)"><input #userInput placeholder="Type a message..."><button type="submit">SUBMIT</button>
</form><h3>Complete Log</h3>
<button type="button" (click)="clearLog()">CLEAR</button>
<ul><li *ngFor="let log of logs; let i=index">{{ logs.length - i }} > {{ log.message }} @ {{ log.timestamp }}</li>
</ul>

This has the feel of a ToDo application. You can log messages and clear the log of messages. Imagine if all the logic from the service was shoved into AppComponent! It would have complicated the code. LoggerService keeps the log-related code encapsulated from the core AppComponent class.

这具有ToDo应用程序的感觉。 您可以记录消息并清除消息日志。 想象一下,如果服务中的所有逻辑都被推到了AppComponent中! 它将使代码复杂化。 LoggerService保留从核心AppComponent类封装的与日志相关的代码。

提取请求 (Fetch Requests)

Here is one more example worth playing around with. This example is possible thanks to typicode’s JSONPlaceholder1. The API is public and free to use.

这是另一个值得一试的例子。 由于typicode的JSONPlaceholder 1 , 因此该示例成为可能。 该API是公开的,可以免费使用。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';// https://jsonplaceholder.typicode.com
// public API created by typicode @ https://github.com/typicodeinterface Post {userId:number;id:number;title:string;body:string;
}@Injectable({providedIn: 'root'
})
export class PlaceholderService {constructor(private http:HttpClient) { }getPosts():Observable<Post[]> {return this.http.get('https://jsonplaceholder.typicode.com/posts');}getPost(id:number):Observable<Post> {return this.http.get(`https://jsonplaceholder.typicode.com/posts/${id}`);}
}

This is more of a stand-alone piece than a fully fleshed out example. Fetch requests tend to work better as an injectable service. The alternative is an over-complicated component. The injected class subscribes to what the PlaceholderService pre-configures.

与完全充实的示例相比,这更像是一个独立的片段。 提取请求倾向于作为可注入服务更好地工作。 替代方案是过于复杂的组件。 注入的类订阅PlaceholderService的预配置。

结论 (Conclusion)

Services and dependency injection are very useful together. They allow developers to encapsulate common logic and inject across multiple different components. This alone is a massive convenience for any future maintenance.

服务和依赖注入一起非常有用。 它们使开发人员可以封装通用逻辑并跨多个不同组件进行注入。 仅此一项就为将来的维护提供了极大的便利。

Injectors work as intermediaries. They mediate between instantiating components and a reservoir of registered services. Injectors offer these instantiable services to their branch children.

注入器充当中介。 它们在实例化组件和已注册服务的存储之间进行调解。 注入器为分支孩子提供这些实例化服务。

See the next few links for more information on services and dependency injection.

有关服务和依赖项注入的更多信息,请参见接下来的几个链接。

Angular资源 (Resources for Angular)

  • Angular Documentation

    角度文档

  • In introduction to Angular dependency injection

    Angular依赖注入简介

  • What is dependency injection and when to use it

    什么是依赖注入以及何时使用它

  • Best Angular code examples

    最佳Angular代码示例

  • Angular GitHub Repository

    Angular GitHub存储库

  • Dependency Injection

    依赖注入

  • Intro to Services and DI

    服务和DI简介

翻译自: https://www.freecodecamp.org/news/angular-services-and-dependency-injection-explained/

框架依赖注入和普通依赖注入

框架依赖注入和普通依赖注入_角服务和依赖注入解释相关推荐

  1. 穹顶灯打不出阴暗面_微服务的阴暗面,解释

    穹顶灯打不出阴暗面 大量的博客文章,白皮书和幻灯片组,宣扬了微服务的优点. 他们谈论微服务如何"提高敏捷性","更具可扩展性",并承诺当您进行切换时,工程师会在 ...

  2. 【SSM框架系列】Spring IoC(控制反转) DI(依赖注入)

    Spring是什么 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Orie ...

  3. python需要依赖注入吗_是否需要使用依赖注入容器?

    译文首发于 是否需要使用依赖注入容器?,转载请注明出处. 本文是依赖注入(Depeendency Injection)系列教程的第 2 篇文章,本系列教程主要讲解如何使用 PHP 实现一个轻量级服务容 ...

  4. java 反转 控制 注入_控制反转和依赖注入

    全2册git版本控制管理(第2版)+ 99.8元 包邮 (需用券) 去购买 > 控制反转(Inversion of Control)即IoC,是一种模式,Spring的核心概念. 依赖注入(De ...

  5. laravel5.2总结--服务容器(依赖注入,控制反转)

    1.依赖 我们定义两个类:class Supperman 和 class Power,现在我们要使用Supperman ,而Supperman 依赖了Power class Supperman { p ...

  6. Spring 依赖注入三种方式的实现,及循环依赖问题的解决(源码+XML配置)

    搬砖啦,搬砖啦,这几天在看Spring相关的书,下面给大家分享一下这几天的心得与收获,Go Go Go! Spring支持两种依赖注入方式,分别是属性注入,构造函数注入.除此之外,Spring还支持工 ...

  7. mysql注入带外通道攻击_防止SQL注入攻击的方法

    防止SQL注入攻击的方法 发布时间:2020-08-25 14:18:13 来源:亿速云 阅读:78 作者:小新 小编给大家分享一下防止SQL注入攻击的方法,相信大部分人都还不怎么了解,因此分享这篇文 ...

  8. java中sql语句怎么把开始和结束时间作为参数写sql查询_聊一聊MyBatis 和 SQL 注入间的恩恩怨怨

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 引言 MyBatis 是一种持久层框架,介于 JDBC 和 Hi ...

  9. sql server ssl安全错误_渗透测试 丨 SQL注入的攻与防

    " 注入攻击漏洞,例如SQL,OS以及LDAP注入.这些攻击发生在当不可信的数据作为命令或者查询语句的一部分,被发送给解释器的时候.攻击者发送的恶意数据可以欺骗解释器,以执行计划外的命令或者 ...

最新文章

  1. 线性回归之正则化线性模型
  2. 关于R和Python的安全机制
  3. Silverlight RIA Services基础专题
  4. Asp中隐藏下载地址
  5. spring 事务-使用@Transactional 注解(事务隔离级别)
  6. Python列表基础
  7. iOS 开发疑难杂症(01)
  8. ctf up怎么写 write_软件测试工程师要不要写工具?
  9. 如何腾出计算机内存,电脑C盘又飘红?教你这样清理内存,可以轻松腾出大量空间...
  10. php.ini设置详解
  11. OFBiz + Opentaps 目录管理 六. 产品目录
  12. java 中鼠标事件_[Java教程]js中鼠标事件总结
  13. Delphi7 请求webservice 方法。
  14. WPS Office Pro 2016 专业版
  15. 简体中文原型设计工具对比
  16. java cropper_Image Cropper 的 JAVA 支持
  17. 【Redis】客户端RedisClient
  18. win7程序关闭后弹出 程序兼容性助手 这个程序可能安装不正确 如果此程序没有正确安装,处理方式
  19. 川藏自驾游的神州租车攻略
  20. eclipse与数据库连接插入或者拿出数据出现乱码该如何解决。

热门文章

  1. 【Windows CMD】设置编码格式
  2. 文件字符输出流 FileWritter java
  3. 字典 dictionary c# 0104
  4. 常量的定义与使用 1006 c#
  5. 视图请求限定装饰器-101.课时101.【Django视图高级】限制请求method装饰器(Av61533158,P101)
  6. javascript-注释-字符串数据类型的方法
  7. 企业级 SpringCloud 教程 (七) 高可用的分布式配置中心(Spring Cloud Config)
  8. layabox2:打地鼠(地鼠显示/停留/受击/消失)
  9. selenium + python自动化测试unittest框架学习(一)selenium原理及应用
  10. NTT通信公司在大阪开通运营容灾数据中心