欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-05 20:30:28
学习目录 angular 4 依赖注入教程之一 依赖注入简介 angular 4 依赖注入教程之二 组件服务注入 angular 4 依赖注入教程...

学习目录

前言

本文属于angular 4 依赖注入学习系列的第四篇,主要介绍了angular 4 依赖注入之factoryprovider的使用,感兴趣的朋友们下面来看看详细的介绍:

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

基础知识

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能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。