Angular 4 依赖注入教程之八 InjectToken的使用
栏目: JavaScript · 发布时间: 7年前
内容简介:Angular 4 依赖注入教程之八 InjectToken的使用
目录
-
Angular 4 依赖注入教程之八 InjectToken的使用
阅读须知
本系列教程的开发环境及开发语言:
基础知识
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
依赖注入教程已经结束了,但其实本教程只介绍了 Angular
依赖注入的部分知识。如果读者有兴趣的话,可以继续了解以下的内容:
-
-
涉及 useClass、useValue、useExisting、useFactory 及 Provider 使用方式。
-
-
-
涉及 multi provider 作用及 Angular 4.x 内部应用。
-
-
-
涉及 forwardRef 的作用及内部工作原理,同时解释 JavaScript 解释器不能自动提升 Class。
-
-
Angular 4.x OpaqueToken & InjectionToken
-
涉及使用字符串作为 Token存在问题,详细介绍如何使用 OpaqueToken、InjectionToken 解决问题。
-
-
-
涉及 IoC 和 DI、DI 在 AngularJS 1.x 中的应用、内部工作原理及存在的问题等。
-
-
-
涉及依赖注入的概念及Angular 4.x 注入器的内部实现 (慎入)。
-
-
Angular Element Injector
-
尚未完成,敬请期待
-
我有话说
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 系统没法做到这点。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First JavaScript Programming
Eric T. Freeman、Elisabeth Robson / O'Reilly Media / 2014-4-10 / USD 49.99
This brain-friendly guide teaches you everything from JavaScript language fundamentals to advanced topics, including objects, functions, and the browser’s document object model. You won’t just be read......一起来看看 《Head First JavaScript Programming》 这本书的介绍吧!