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


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 依赖注入学习系列的第四篇,主要介绍了Angular 4 依赖注入之FactoryProvider的使用,感兴趣的朋友们下面来看看详细的介绍:

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

  • Angular 4 +
  • Angular CLI
  • TypeScript

基础知识

FactoryProvider 的作用

FactoryProvider 用于告诉 Injector (注入器),通过调用 useFactory 对应的函数,返回 Token 对应的依赖对象。

FactoryProvider 的使用

function serviceFactory() { 
 return new Service();
}

const provider: FactoryProvider = {
 provide: 'someToken', useFactory: serviceFactory, deps: []
};

FactoryProvider 接口

export interface FactoryProvider {
 // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、
 // OpaqueToken的实例或字符串
 provide: any;
 // 设置用于创建对象的工厂函数
 useFactory: Function;
 // 依赖对象列表
 deps?: any[];
 // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖
 // 对象列表
 multi?: boolean;
}

FactoryProvider

介绍完基础知识,接下来我们马上进入正题。不知道大家是否还记得,之前我们创建过的 HeroComponent 组件:

import { Component, OnInit } from '@angular/core';
import { HeroService } from '../hero.service';

@Component({
 selector: 'app-hero',
 template: `
 <ul>
 <li *ngFor="let hero of heros">
 ID: {{hero.id}} - Name: {{hero.name}}
 </li>
 </ul>
 `
})
export class HeroComponent implements OnInit {

 constructor(private heroService: HeroService) { }

 heros: Array<{ id: number; name: string }>;

 ngOnInit() {
 this.heros = this.heroService.getHeros();
 }
}

那么现在问题来了,假设我们想在获取英雄数据时,输出调试信息,那应该怎么办?What ~,这个问题不是很简单么,直接使用 console.log API 输出相应信息不就行了么:

console.log('Fetching heros...');
this.heros = this.heroService.getHeros();

那问题又来了,如果多个组件都使用 HeroService 去获取英雄数据,那么是不是每个组件都得添加对应的语句。另外如果要修改输出的调试信息,那就得修改程序中多个地方。其实我们一般只需要在开发阶段,输出调试信息,因此上面的方案不合理,也不够灵活。

其实我们可以借鉴之前引入 HeroService 服务的思路,创建一个 LoggerService 来解决上面提到的问题。

创建 LoggerService 服务

export class LoggerService {
 constructor(private enable: boolean) { }

 log(message: string) {
 if(this.enable) {
  console.log(`LoggerService: ${message}`);
 }
 }
}

配置 LoggerService 服务

@NgModule({
 ...
 providers: [
 HeroService,
 LoggerService
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }

使用 LoggerService 服务

import { Component, OnInit } from '@angular/core';
import { HeroService } from '../hero.service';
import { LoggerService } from './../logger.service';

@Component({
 selector: 'app-hero',
 template: `
 <ul>
 <li *ngFor="let hero of heros">
 ID: {{hero.id}} - Name: {{hero.name}}
 </li>
 </ul>
 `
})
export class HeroComponent implements OnInit {
 heros: Array<{ id: number; name: string }>;

 constructor(private heroService: HeroService,
 private loggerService: LoggerService) { }

 ngOnInit() {
 this.loggerService.log('Fetching heros...');
 this.heros = this.heroService.getHeros();
 }
}

以上代码运行后会抛出以下异常信息:

Uncaught Error: Can't resolve all parameters for LoggerService: (?).

有的读者,眼睛一亮,可能是你在创建 LoggerService 服务时,忘记使用 @Injectable 装饰器了。哈哈,其实我是故意的,但我加上 @Injectable() 后,还是抛出了以下异常:

ERROR Error: No provider for Boolean!

为什么会出现上面的异常信息呢?我们再看一下前面创建的 LoggerService 服务:

export class LoggerService {
 constructor(private enable: boolean) { }
 // ...
}

在 Angular 中我们通过构造注入的方式注入依赖对象, private enable: boolean 这种方式表示我们要注入 Type 类型的对象。然后 boolean 是表示基本数据类型,并不是所需的 Type 类型:

export function isType(v: any): v is Type<any> {
 return typeof v === 'function';
}

接下来我们再来看一下最早抛出的异常:

Uncaught Error: Can't resolve all parameters for LoggerService: (?).

其实问题的答应也在 LoggerService 类的构造函数中,在创建 LoggerService 对象时,我们需要设置 enable 参数的值。那么如何解决呢? 当然可以使用我们的主角 - FactoryProvider 。

具体如下:

使用 FactoryProvider

@NgModule({
 ...,
 providers: [
 HeroService,
 {
 provide: LoggerService, 
 useFactory: () => {
 return new LoggerService(true);
 }
 }
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }

当更新完代码,然后再来一个华丽的保存操作,最后打开你的控制台,你将看到预期的输出信息:

LoggerService: Fetching heros...

难道就这样结束了,关于 FactoryProvider 的相关内容先告一段落,下一篇我们将介绍如何使用 FactoryProvider 配置依赖对象。

总结

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

Javascript 相关文章推荐
javascript css styleFloat和cssFloat
Mar 15 Javascript
JQuery操作表格(隔行着色,高亮显示,筛选数据)
Feb 23 Javascript
JS 控件事件小结
Oct 31 Javascript
js 回车提交表单两种实现方法
Dec 31 Javascript
Javascript中产生固定结果的函数优化技巧
Jan 16 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
Aug 26 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
Oct 25 Javascript
JQuery实现列表中复选框全选反选功能封装(推荐)
Nov 24 Javascript
利用node.js本地搭建HTTP服务器
Apr 19 Javascript
简单谈谈关于 npm 5.0 的新坑
Jun 08 Javascript
vue.js实现标签页切换效果
Jun 07 Javascript
vue实现桌面向网页拖动文件的示例代码(可显示图片/音频/视频)
Mar 01 Vue.js
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 #Javascript
Angular 4依赖注入学习教程之组件服务注入(二)
Jun 04 #Javascript
JavaScript箭头(arrow)函数详解
Jun 04 #Javascript
Angular 4依赖注入学习教程之简介(一)
Jun 04 #Javascript
angularJs中datatable实现代码
Jun 03 #Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
Jun 03 #Javascript
详解JavaScript调用栈、尾递归和手动优化
Jun 03 #Javascript
You might like
PHP和javascript常用正则表达式及用法实例
2014/07/01 PHP
全面解读PHP的人气开发框架Laravel
2015/10/15 PHP
php中注册器模式类用法实例分析
2015/11/03 PHP
PHP实现小偷程序实例
2016/10/31 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
限制文本字节数js代码
2007/03/06 Javascript
Javascript操作cookie的函数代码
2012/10/03 Javascript
js/jquery获取浏览器窗口可视区域高度和宽度以及滚动条高度实现代码
2012/12/17 Javascript
基于zepto.js实现仿手机QQ空间的大图查看组件ImageView.js详解
2015/03/05 Javascript
AngularJS的内置过滤器详解
2015/05/14 Javascript
详解Webwork中Action 调用的方法
2016/02/02 Javascript
详解原生js实现offset方法
2017/06/15 Javascript
Node.js学习之TCP/IP数据通讯(实例讲解)
2017/10/11 Javascript
vue2 设置router-view默认路径的实例
2018/09/20 Javascript
详解ES6中的 Set Map 数据结构学习总结
2018/11/06 Javascript
Vue分页插件的前后端配置与使用
2019/10/09 Javascript
vue使用prop可以渲染但是打印台报错的解决方式
2019/11/13 Javascript
js实现前端界面导航栏下拉列表
2020/08/27 Javascript
UEditor 自定义图片视频尺寸校验功能的实现代码
2020/10/20 Javascript
Vue 集成 PDF.js 实现 PDF 预览和添加水印的步骤
2021/01/22 Vue.js
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
初步认识Python中的列表与位运算符
2015/10/12 Python
pandas 选择某几列的方法
2018/07/03 Python
mac安装pytorch及系统的numpy更新方法
2018/07/26 Python
pytorch训练imagenet分类的方法
2018/07/27 Python
详解django中url路由配置及渲染方式
2019/02/25 Python
解决Python import docx出错DLL load failed的问题
2020/02/13 Python
css3实现信纸/同学录效果的示例代码
2018/12/11 HTML / CSS
美国最流行的男士时尚网站:Touch of Modern
2018/02/05 全球购物
牵手50香港:专为黄金岁月的单身人士而设的交友网站
2020/08/14 全球购物
摄影专业毕业生求职信
2014/08/05 职场文书
维稳承诺书
2015/01/20 职场文书
颐和园的导游词
2015/01/30 职场文书
搞笑老公保证书
2015/02/26 职场文书
网络安全倡议书(3篇)
2019/09/18 职场文书
Redis集群新增、删除节点以及动态增加内存的方法
2021/09/04 Redis