by Dor Moshe

通过Dor Moshe

Angular的后院:解决 组件依赖关系 (Angular’s Backyard: The Resolving of Components Dependencies)

This article originally appeared on dormoshe.io

这篇文章 最初出现在dormoshe.io

Many of us use the Hierarchical Dependency Injection mechanism of Angular. We use it through a service or a component to resolve another service or provider. But, do we know what Angular does in order to resolve the dependencies? Probably not, because Angular takes care of what we need to use it as a black box.

我们中的许多人都使用Angular的分层依赖注入机制。 我们通过服务或组件使用它来解析另一个服务或提供者。 但是,我们知道Angular为了解决依赖关系做什么吗? 可能不是,因为Angular会照顾我们需要将其用作黑匣子的情况。

In this article, we’ll open the black box and explore the code of the component dependencies resolution mechanism.

在本文中,我们将打开黑盒,并探索组件依赖关系解析机制的代码。

回到基础 (Back to the basics)

Dependency Injection (DI) is a powerful pattern for managing code dependencies. Angular’s DI system creates and delivers dependent services “just-in-time”. Angular has its own DI framework, and we can’t build an Angular application without it.

依赖注入 (DI)是一种用于管理代码依赖关系的强大模式。 Angular的DI系统可以 “及时” 创建并提供相关服务 。 Angular有自己的DI框架,没有它我们就无法构建Angular应用程序。

The Angular DI system is actually a Hierarchical system. This system supports nested injectors in parallel with the component tree. An injector creates dependencies using providers. We can reconfigure the injectors at any level of that component tree. Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.

Angular DI系统实际上是一个层次结构 系统。 该系统支持与组件树并行的嵌套进样器。 注入程序使用提供程序创建依赖关系。 我们可以在该组件树的任何级别重新配置注入器。 在幕后,每个组件都使用为该组件本身定义的零个,一个或多个提供程序来设置自己的注入器

解决顺序 (Resolution Order)

The hierarchical DI has an order to the resolution of the dependencies. When a component requests a dependency, if it exists in the @Component.providers array (the component injector), then this dependency will be supplied.

层次化DI对依存关系的解析具有顺序。 当组件请求依赖项时,如果它存在于@Component.providers数组(组件注入器)中,则将提供此依赖项。

Elsewhere, Angular continues to the parent component injector and checks again and again. If Angular doesn’t find an ancestor, it will supply this dependency via the application main injector. This is the core concept of the hierarchical DI mechanism.

在其他地方,Angular继续使用父组件注入器并一次又一次地检查。 如果Angular找不到祖先,它将通过应用程序主注入器提供此依赖关系。 这是分层DI机制的核心概念。

让我们看一下代码 (Let’s see the code)

When Angular instantiates a component, it calls the resolveDep function. This function's signature contains the component view container, the element, the dependency definition and some more arguments. We will focus on the component view and the dependency object. The dependency object contains only one dependency of the component.

Angular实例化组件时,它将调用resolveDep函数。 该函数的签名包含组件视图容器,元素,依赖项定义和更多参数。 我们将专注于组件视图和依赖对象。 依赖性对象仅包含组件的一种依赖性。

Here is the resolveDep function skeleton from the Angular GitHub repository:

这是Angular GitHub存储库中的resolveDep函数框架:

The function skeleton contains the main concepts of the resolution, without the edge cases. The full code can be found here. In the next parts, we will explore the function skeleton.

函数框架包含分辨率的主要概念,不包含边缘情况。 完整的代码可以在这里找到。 在接下来的部分中,我们将探索功能框架。

保沙 (Pausa)

The Exclamation mark is a new feature of Typescript 2.0. The ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Angular uses this feature frequently, so we should not be afraid.

感叹号是Typescript 2.0的新功能。 ! 在类型检查器无法得出结论的上下文中,可以使用后缀表达式运算符来断言其操作数是非null且未定义的。 Angular经常使用此功能,因此我们不用担心。

第1部分-准备 (Part 1 — Preparation)

The const startView = view; code saves the original view (the view container of the component) in a variable because the view variable will change soon.

const startView = view; 代码将原始视图(组件的视图容器)保存在一个变量中,因为view变量将很快更改。

The const tokenKey = depDef.tokenKey; code fetches the tokenKey or the dependency key, for example, HeroService_4. This key builds by the dependency name and a generated number to handle the dependency uniquely.

const tokenKey = depDef.tokenKey; 代码获取tokenKey或依赖项键,例如HeroService_4 。 该键由依赖项名称和生成的数字构建,以唯一地处理依赖项。

第2部分-源组件和祖先搜索 (Part 2 —Source component and Ancestors search)

The while loop implements the stages of checking the source @Component.providers and the ancestor components. According to the dependency token key, the source component providers will be checked in lines 1–3:

while循环实现检查源@Component.providers和祖先组件的阶段。 根据依赖性令牌密钥,将在第1–3行中检查源组件提供者:

If the provider exists on line 4, then the source component satisfies the dependency. So, if the dependency was instantiated in the past on line 6, the instance will return by the resolveDep function at line 10. If this is the first time that the component or its children ask for the dependency it will be created at line 7 and will return by the resolveDep function at line 10.

如果提供程序存在于第4行,则源组件满足依赖性。 因此,如果依赖关系是在过去的第6行实例化的,则实例将在第10行由resolveDep函数返回。如果这是组件或其子级第一次请求依赖关系,它将在第7行创建,然后将由第10行的resolveDep函数返回。

If the dependency is not found in the view component injector, the elDef = viewParentEl(view) !; and view = view.parent !; will be called to advance the variable to the parent element. The while loop will continue running until the dependency is found in the ancestor injector. If the dependency is still not found after checking all ancestors, the while loop will end and the third part will come into action.

如果在view组件注入器中未找到依赖项,则elDef = viewParentEl(view) !;view = view.parent !; 将被调用以将变量前进到父元素。 while循环将继续运行,直到在祖先注入器中找到相关性为止。 如果在检查所有祖先后仍未找到依赖项,则while循环将结束,并且第三部分将开始起作用。

第3部分-根注射器 (Part 3 — Root injector)

If come to this part, the dependency can’t be satisfied by any of the component ancestors injectors. Then the startView or the source component will be checked at line 1:

如果涉及到这一部分,则任何组件祖先注入器都无法满足这种依赖性。 然后将在第1行检查startView或源组件:

If the source component or one of its ancestor components was loaded by the Router Outlet (the router component), the root injector is the Outlet Injector. This injector supplies some dependencies like the Router service. Otherwise, the root injector is the bootstrap component’s injector.

如果源组件或其祖先组件之一是由路由器出口(路由器组件)加载的,则注入器为出口注入器 。 该注入器提供了一些依赖性,例如路由器服务。 否则,根注入器是自举组件的注入器。

If the dependency is found at line 3, then the value will be returned by the resolveDep function. In the other case, part 4 will come into action.

如果在第3行找到依赖项,那么resolveDep函数将返回该值。 在其他情况下,第4部分将生效。

第4部分-应用模块注入器 (Part 4 — Application module injector)

When we come to this part, it means that the dependency can’t be satisfied by part 2 and part 3. This is the last chance to satisfy the dependency. This part’s code tries to get the dependency from the application module injector or the root module. This module contains the application-wide dependencies:return startView.root.ngModule.injector.get(depDef.token,notFoundValue);

当涉及到这一部分时,这意味着第2部分和第3部分不能满足依赖关系。这是满足依赖关系的最后机会。 这部分的代码试图从应用程序模块注入器或根模块获取依赖关系。 此模块包含应用程序范围的依赖项: return startView.root.ngModule.injector.get(depDef.token,notFoundValue);

This part finishes the resolveDep flow. If the dependency is not found, then Angular can’t satisfy this dependency and it should throw an exception.

本部分完成resolveDep流程。 如果找不到依赖关系,则Angular无法满足此依赖关系,因此应引发异常。

结论 (Conclusion)

The Hierarchical DI is a core feature that Angular leans on a lot. Sometimes, the resolution process looks complicated and long. It’s very convenient to leave Angular to manage this flow and enjoy the ease of use. Now, after we hiked in the backyard of the component dependency resolution, we know what to expect when we use it.

分层DI是Angular所依赖的一项核心功能。 有时,解析过程看起来很复杂且漫长。 离开Angular管理此流程并享受易用性非常方便。 现在,当我们在组件依赖关系解决方案的后院爬升之后,我们知道使用它时会发生什么。

You can follow me on dormoshe.io or Twitter to read more about Angular, JavaScript and web development.

您可以在dormoshe.io或Twitter上关注我,以了解有关Angular,JavaScript和Web开发的更多信息。

翻译自: https://www.freecodecamp.org/news/angulars-backyard-the-resolving-of-component-dependencies-2015b40e5bd1/

Angular的后院:组件依赖关系的解决相关推荐

  1. CSE 支持spring 4/5 以及spring boot 1/2 maven组件依赖关系配置参考

    [摘要] 本文介绍了CSE如何使用Spring 4或者Spring 5,以及在Spring Boot 1和Spring Boot 2中如何集成CSE,重点介绍了CSE提供的maven管理器,以及如何使 ...

  2. Ubuntu安装deb软件包错误(依赖关系问题)解决

    Ubuntu安装deb软件包错误(依赖关系问题)解决 参考文章: (1)Ubuntu安装deb软件包错误(依赖关系问题)解决 (2)https://www.cnblogs.com/congyucn/p ...

  3. IDEA maven项目查自动查看依赖关系,解决包冲突问题

    IDEA maven项目查自动查看依赖关系,解决包冲突问题 参考文章: (1)IDEA maven项目查自动查看依赖关系,解决包冲突问题 (2)https://www.cnblogs.com/jpfs ...

  4. ubuntu中手动编译源码安装Xorg-server过程中依赖关系的解决

    ubuntu中手动编译源码安装Xorg-server过程中依赖关系的解决 在linux系统中手动编译源码安装软件包的过程是非常痛苦的,然而这一个多星期以来我是强忍住脾气体验了一把,虽然面对慢的令人发指 ...

  5. linux系统软件包依赖关系,Ubuntu解决包依赖关系

    Ubuntu解决包依赖关系: 出现的错误有: 有一些软件包无法被安装.如果您用的是 unstable 发行版,这也许是 因为系统无法达到您要求的状态造成的.该版本中可能会有一些您需要的软件 包尚未被创 ...

  6. 关于deepin应用商店一直显示正在安装安装时出现有未能满足的依赖关系的解决方法

    文章目录 问题描述 解决过程 总结 问题描述 deepin版本 社区版 20.2.3 内核 5.10.50-amd64-desktop 在应用商店下载应用,有三个或者超过三个同时下载,最后会一直显示安 ...

  7. java模块依赖关系_链接模块依赖关系未解决

    我正面临与 npm link 相关的问题 这是在本地发布模块并在其他角度应用程序中使用它们的情况 . 我有2个应用程序 1) app-core (published locally) 2) app-m ...

  8. 软件包有未满足的依赖关系

    问题:软件包有未满足的依赖关系. 解决:更新源列表       (以下转自http://wiki.ubuntu.org.cn/Qref/Source) 如何使用Ubuntu Night Ubuntu ...

  9. 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。ubu

    有一些软件包无法被安装.如果您用的是 unstable 发行版,这也许是 因为系统无法达到您要求的状态造成的.该版本中可能会有一些您需要的软件 包尚未被创建或是它们已被从新到(Incoming)目录移 ...

最新文章

  1. lr手工添加关联函数的步骤:
  2. Linux开发板怎么用madplay,Linux中madplay 音乐播放器移植步骤
  3. linux 服务器账号及安全杂谈
  4. android AVB2.0(四)libavb库介绍
  5. CCF201512-1 数位之和
  6. kafka 集群_kafka 集群及原理
  7. 杭电5620 KK's Steel
  8. C++、C#、Java、Python、可以获取L2行情实时数据吗?
  9. 订餐系统实验报告java_订餐系统的java实训报告.ppt
  10. linux 查看CPU核数
  11. 防止表单重复提交的解决方案
  12. 1.初始Hadoop大数据技术
  13. 【云计算学习教程】与云计算相关的开源软件有哪些?
  14. 微积分近似计算公式:中点、梯形、辛普森
  15. 曲线救国!通过VirtualBox让Windows Server 2008 R2也用上蓝牙
  16. Memcached对象缓存详解
  17. 用Python统计中英文词频
  18. ubuntu 的apt 命令详解
  19. 读书笔记-白话机器学习的数学
  20. 自动设置为兼容模式html5,360浏览器怎么样让某网站自动以兼容模式打开

热门文章

  1. layou split 属性
  2. Springboot集成BeanValidation扩展一:错误提示信息加公共模板
  3. 【CZY选讲·Yjq的棺材】
  4. mvn编写主代码与测试代码
  5. JAVA静态和非静态内部类
  6. 逻辑回归(Logistic Regression, LR)又称为逻辑回归分析,是分类和预测算法中的一种。通过历史数据的表现对未来结果发生的概率进行预测。例如,我们可以将购买的概率设置为因变量,将用户的
  7. BPMN2.0-概要
  8. 同一服务器部署多个tomcat时的端口号修改详情
  9. Laravel Composer 命令大全
  10. 如何用 Python 实现 Web 抓取?