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 相关文章推荐
jQuery Flash/MP3/Video多媒体插件
Jan 18 Javascript
UserData用法总结 lanyu出品
Jul 01 Javascript
利用JQuery和JS实现奇偶行背景颜色自定义效果
Nov 19 Javascript
location.href用法总结(最主要的)
Dec 27 Javascript
JS+CSS实现模仿浏览器网页字符查找功能的方法
Feb 26 Javascript
jQuery实现文本展开收缩特效
Jun 03 Javascript
深入解析Backbone.js框架的依赖库Underscore.js的作用
May 07 Javascript
vue单页应用加百度统计代码(亲测有效)
Jan 31 Javascript
解决angular双向绑定无效果,ng-model不能正常显示的问题
Oct 02 Javascript
js简单遍历获取对象中的属性值的方法示例
Jun 19 Javascript
layui默认选中table的CheckBox复选框方法
Sep 19 Javascript
JS操作JSON常用方法(10w阅读)
Dec 06 Javascript
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
BBS(php &amp; mysql)完整版(七)
2006/10/09 PHP
php 日期和时间的处理-郑阿奇(续)
2011/07/04 PHP
PHP中include与require使用方法区别详解
2013/10/19 PHP
PHP中set error handler函数用法小结
2015/11/11 PHP
小型js框架veryide.librar源代码
2009/03/05 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
2013/10/12 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
深入理解JS addLoadEvent函数
2016/05/20 Javascript
JS HTML5实现拖拽移动列表效果
2020/08/27 Javascript
BootStrap下拉框在firefox浏览器界面不友好的解决方案
2016/08/18 Javascript
JS代码实现百度地图 画圆 删除标注
2016/10/12 Javascript
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示实例
2016/12/06 Javascript
JavaScript中的toString()和toLocaleString()方法的区别
2017/02/15 Javascript
Angular排序实例详解
2017/06/28 Javascript
vue下跨域设置的相关介绍
2017/08/26 Javascript
浅谈React Native Flexbox布局(小结)
2018/01/08 Javascript
代码详解JS操作剪贴板
2018/02/11 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
2018/03/09 Javascript
微信小程序适配iphoneX的实现方法
2018/09/18 Javascript
解决vue项目中页面调用数据 在数据加载完毕之前出现undefined问题
2019/11/14 Javascript
压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)
2020/02/03 Javascript
Vue和React有哪些区别
2020/09/12 Javascript
Python os模块介绍
2014/11/30 Python
Python中每次处理一个字符的5种方法
2015/05/21 Python
Python读写unicode文件的方法
2015/07/10 Python
Python3内置模块之base64编解码方法详解
2019/07/13 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
CSS3实现多样的边框效果
2018/05/04 HTML / CSS
优秀演讲稿范文
2013/12/29 职场文书
奶茶专卖店创业计划书
2014/01/18 职场文书
初一科学教学反思
2014/01/27 职场文书
工程项目经理任命书
2014/06/05 职场文书
工程服务质量承诺书
2015/04/29 职场文书
小学四年级作文之最感动的一件事
2019/11/01 职场文书
在项目中使用redis做缓存的一些思路
2021/09/14 Redis
3050和2060哪个好 性能差多少 差距有多大 谁更有性价比
2022/06/17 数码科技