Angular 4依赖注入学习教程之InjectToken的使用(八)


Posted in Javascript onJune 04, 2017

学习目录

  • Angular 4 依赖注入教程之一 依赖注入简介
  • Angular 4 依赖注入教程之二 组件服务注入
  • Angular 4 依赖注入教程之三 ClassProvider的使用
  • Angular 4 依赖注入教程之四 FactoryProvider的使用
  • Angular 4 依赖注入教程之五 FactoryProvider配置依赖对象
  • Angular 4 依赖注入教程之六 Injectable 装饰器
  • Angular 4 依赖注入教程之七 ValueProvider的使用
  • Angular 4 依赖注入教程之八 InjectToken的使用

本文主要给大家介绍的是关于Angular 4依赖注入之InjectToken使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:

本系列教程的开发环境及开发语言:

  • Angular 4 +
  • Angular CLI
  • TypeScript

基础知识

OpaqueToken 简介

OpaqueToken 用于创建可在 Provider 中使用的 Token。

OpaqueToken 类的定义

export class OpaqueToken {
 constructor(protected _desc: string) {}

 toString(): string { return `Token ${this._desc}`; }
}

OpaqueToken 类的使用

import { ReflectiveInjector } from '@angular/core';

var t = new OpaqueToken("value");
var injector = ReflectiveInjector.resolveAndCreate([
 {provide: t, useValue: "bindingValue"}
]);
injector.get(t); // "bindingValue"

InjectionToken 简介

InjectionToken 用于创建可在 Provider 中使用的 Token。

InjectionToken 类的定义

export class InjectionToken<T> extends OpaqueToken {
 private _differentiate_from_OpaqueToken_structurally: any;
 constructor(desc: string) { super(desc); }

 toString(): string { return `InjectionToken ${this._desc}`; }
}

InjectionToken 类的使用

import { ReflectiveInjector } from '@angular/core';

var t = new InjectionToken<string>("value");
var injector = ReflectiveInjector.resolveAndCreate([
 {provide: t, useValue: "bindingValue"}
]);
injector.get(t); // "bindingValue"

InjectionToken

在介绍 InjectionToken 相关内容之前,我们先回顾一下 "ValueProvider的使用" 这篇中我们介绍的内容:

使用 ValueProvider

@NgModule({
 ...,
 providers: [
 {
 provide: 'apiUrl',
 useValue: 'http://localhost:4200/heros'
 }
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }

更新 HeroService 服务

@Injectable()
export class HeroService {
 constructor(private loggerService: LoggerService,
 private http: Http,
 @Inject('apiUrl') private apiUrl) { }

 getHeros(): Observable<Array<{ id: number; name: string }>> {
 this.loggerService.log('Fetching heros...');
 return this.http.get(this.apiUrl)
 .map(res => res.json())
 }
}

为了能够更方便地管理与维护 apiUrl 地址,我们利用了 ValueProvider 和 Inject 装饰器。一切看起来非常顺利,但某一天假设我们引入了一个第三方库 - third-lib.ts,该文件的内容如下所示:

export const THIRD_PARTY_PROVIDERS = [
 {
 provide: 'apiUrl',
 useValue: 'Other Url'
 }
];

接着我们在 AppModule 中配置对应的 Provider 信息,具体如下:

import { THIRD_PARTY_PROVIDERS } from './third-party';

@NgModule({
 ...,
 providers: [
 {
 provide: 'apiUrl',
 useValue: 'http://localhost:4200/heros'
 },
 THIRD_PARTY_PROVIDERS
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }

当更新完上述代码,成功保存后,你会发现 http://localhost:4200/ 页面,又是空空如也了。这时如果我们打开开发者工具,切换到 Console 面板你会看到如下异常信息:

GET http://localhost:4200/Other%20value 404 (Not Found)

什么情况,我们的英雄信息的接口地址被替换了,其实真正的原因是使用字符串作为 Token 引起冲突了。那么怎么解决呢?最简单的方式是对调一下 ValueProvider 与 THIRD_PARTY_PROVIDERS 的位置。你会发现在 http://localhost:4200/ 页面,你又能看到英雄信息。当然这不能解决本质问题,因为这样会导致你引入的第三方库不能正常工作。

相信很多读者已经习惯了我的 "套路",当然要让我们的主角 - InjectionToken 出马,来解决这个问题咯。为了统一管理应用中的 Token 信息 ,我们新建一个 app.tokens.ts 文件来保存应用中的 Token 信息。

该文件的具体内容如下:

import { InjectionToken } from '@angular/core';

export const API_URL = new InjectionToken<string>('apiUrl');

接下来我们在更新一下 AppModule:

import { API_URL } from './app.tokens';

@NgModule({
 ...,
 providers: [
 {
 provide: API_URL,
 useValue: 'http://localhost:4200/heros'
 },
 THIRD_PARTY_PROVIDERS
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }

然后在更新 HeroService 服务,具体更新内容如下:

import { API_URL } from './app.tokens';

@Injectable()
export class HeroService {
 constructor(private loggerService: LoggerService,
 private http: Http,
 @Inject(API_URL) private apiUrl) { }
}

当更新完上述代码,成功保存后,你会发现 http://localhost:4200/ 页面,又能正常显示英雄信息了。问题已经解决了,但其实这是因为我们使用了不同的 Token 。我们再来验证一个问题:

import { InjectionToken } from '@angular/core';

const API_URL = new InjectionToken<string>('apiUrl');

export const THIRD_PARTY_PROVIDERS = [
 {
 provide: API_URL,
 useValue: 'Other value'
 }
];

你会发现更新完 third-lib.ts 库,且成功保存后,在 http://localhost:4200/ 页面,还是能正常显示英雄信息。此时,我们的 Angular 4 依赖注入教程已经结束了。

我有话说

OpaqueToken 与 InjectionToken 有什么区别?

相同点

  • 它们都是用于创建可在 Provider 中使用的 Token。

不同点

  • OpaqueToken 是 Angular 2.x 版本中引入的类。
  • InjectionToken 是在 Angular 4.x 版本中引入的类,该类继承于 OpaqueToken,且引入了泛型用于定义所关联的依赖对象的类型。

AngularJS 1.x DI 系统存在的问题

  • 内部缓存:AngularJS 1.x 应用程序中所有的依赖项都是单例,我们不能灵活地控制是否使用新的实例。
  • 命名空间冲突: 在系统中我们使用字符串来标识服务 (Service) 的名称,假设我们在项目中已有一个 CarService,然而第三方库中也引入了同样的服务,这样的话就容易出现冲突。
  • DI 耦合度太高: AngularJS 1.x 中 DI 功能已经被框架集成了,我们不能单独使用它的依赖注入功能。
  • 未能和模块加载器结合: 在浏览器环境中,很多场景都是异步的过程,我们需要的依赖模块并不是一开始就加载好的,或许我们在创建的时候才会去加载依赖模块,再进行依赖创建,而 AngularJS 1.x 的 DI 系统没法做到这点。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者使用Angular 4能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript 强制类型转换函数
May 17 Javascript
键盘KeyCode值列表汇总
Nov 26 Javascript
js代码实现无缝滚动(文字和图片)
Aug 20 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 Javascript
原生js实现返回顶部缓冲效果
Jan 18 Javascript
Bootstrap警告(Alerts)的实现方法
Mar 22 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
Aug 04 Javascript
React为 Vue 引入容器组件和展示组件的教程详解
May 03 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
May 24 jQuery
详解如何在vue项目中使用eslint+prettier格式化代码
Nov 10 Javascript
uni-app自定义导航栏按钮|uniapp仿微信顶部导航条功能
Nov 12 Javascript
JavaScript创建表格的方法
Apr 13 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
Jun 04 #Javascript
Angular 4依赖注入学习教程之Injectable装饰器(六)
Jun 04 #Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
Jun 04 #Javascript
JavaScript基础之this详解
Jun 04 #Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
Jun 04 #Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 #Javascript
Angular 4依赖注入学习教程之组件服务注入(二)
Jun 04 #Javascript
You might like
ThinkPHP内置jsonRPC的缺陷分析
2014/12/18 PHP
php单链表实现代码分享
2016/07/04 PHP
Linux下 php7安装redis的方法
2018/11/01 PHP
利用location.hash实现跨域iframe自适应
2010/05/04 Javascript
js 创建快捷方式的代码(fso)
2010/11/19 Javascript
jquery打开直接跳到网页最下面、最低端实现代码
2013/04/22 Javascript
多个jQuery版本共存的处理方案
2015/03/17 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
2015/11/26 Javascript
简单对比分析JavaScript中的apply,call与this的使用
2015/12/04 Javascript
jQuery动态加载css文件实现方法
2016/06/15 Javascript
对js eval()函数的一些见解
2016/08/15 Javascript
JS求解三元一次方程组值的方法
2017/01/03 Javascript
js时间戳和c#时间戳互转方法(推荐)
2017/02/15 Javascript
requirejs + vue 项目搭建详解
2017/06/16 Javascript
在vue中高德地图引入和轨迹的绘制的实现
2019/10/11 Javascript
JavaScript canvas基于数组生成柱状图代码实例
2020/03/06 Javascript
[01:00]DOTA2 store: Collection of Artisan's Wonders
2015/08/12 DOTA
Python基于回溯法子集树模板解决选排问题示例
2017/09/07 Python
python实现txt文件格式转换为arff格式
2018/05/31 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
python使用pip安装SciPy、SymPy、matplotlib教程
2019/11/20 Python
tensorflow 模型权重导出实例
2020/01/24 Python
python 获取当前目录下的文件目录和文件名实例代码详解
2020/03/10 Python
使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例
2020/03/16 Python
Python引入多个模块及包的概念过程解析
2020/09/21 Python
python绘制分布折线图的示例
2020/09/24 Python
关于python tushare Tkinter构建的简单股票可视化查询系统(Beta v0.13)
2020/10/19 Python
DogBuddy荷兰:找到你最完美的狗保姆
2019/04/17 全球购物
法国一家多品牌成衣精品中/高档商店:Graduate Store
2019/08/28 全球购物
Canal官网:巴西女性时尚品牌
2019/10/16 全球购物
Ariat英国官网:为世界顶级马术运动员制造最优质的鞋类和服装
2020/02/14 全球购物
中学教师实习自我鉴定
2013/09/28 职场文书
毕业生怎样写好自荐信
2013/11/11 职场文书
俄语专业职业生涯规划
2014/02/26 职场文书
购房委托书范本
2014/09/18 职场文书