AngularJS 2 Provider
admin
2023-07-31 13:20:23
0

依赖注入(DI) 是 Angular 2 的核心,在深入了解DI的工作原理之前,我们必须先搞清楚 Provider 的概念。

在 Angular 2 中我们使用 Provider 来描述与 Token 关联的依赖对象的创建方式。Angular 2 中依赖对象的创建方式有四种,它们分别是:

  • useClass

  • useValue

  • useExisting

  • useFactory

useClass

@Injectable()
export class ApiService {   constructor(      
    public http: Http,       
    public loadingCtrl: LoadingController) {   }   
    ...
}
    
@NgModule({  ...  
    providers: [ 
     // 可使用简洁的语法,即直接使用ApiService
    { provide: ApiService, useClass: ApiService }  
]})
export class CoreModule { }

useValue

{ provide: 'API_URL', useValue: 'http://my.api.com/v1' }

useExisting

{ provide: 'ApiServiceAlias', useExisting: ApiService }

useFactory

export function configFactory(config: AppConfig) {  
    return () => config.load();
}

@NgModule({  
    ...
    providers: [ 
    { provide: APP_INITIALIZER, useFactory: configFactory, deps: [AppConfig],
         multi: true }  
]})
export class CoreModule { }

使用 Provider 的正确姿势

1.创建 Token

Token 的作用是用来标识依赖对象,Token值可能是 Type、InjectionToken、OpaqueToken 类的实例或字符串。通常不推荐使用字符串,因为如果使用字符串存在命名冲突的可能性比较高。在 Angular 4.x 以前的版本我们一般使用 OpaqueToken 来创建 Token,而在 Angular 4.x 以上的版本版本,推荐使用 InjectionToken 来创建 Token 。详细的内容可以参考, 如何解决 Angular 2 中 Provider 命名冲突。

2.根据实际需求选择依赖对象的创建方式,如 useClass 、useValue、useExisting、useFactory

3.在 NgModule 或 Component 中注册 providers

4.使用构造注入的方式,注入与 Token 关联的依赖对象

/*** 封装Http服务,如在每个Http的请求头中添加token,类似于Ng1.x中的拦截器*/
@Injectable() export class ApiService {   
    constructor(    
      // 注入Angular 2 中的Http服务,与Ng1.x的区别:   
      // 在Ng1.x中调用Http服务后,返回Promise对象   
      // 在Ng2.x中调用Http服务后,返回Observable对象      
      public http: Http) {    }   
...}
      
/*** AppModule*/
@NgModule({ 
    // 可使用简洁的语法,即直接使用ApiService
 ...  providers: [{ provide: ApiService, useClass: ApiService } 
]})
export class AppModule { }

/*** 系统首页*/
@Component({  
    selector: 'page-home',
    templateUrl: 'home.html'
})
export class HomePage {  
    constructor(
         // 使用构造注入的方式,注入ApiService的实例对象 
        public apiService: ApiService) { }
        
   ngOnInit(): void {    
       // 获取首页相关的数据
       this.apiService.get(HOME_URL)
       .map(res => res.json()) // 返回的res对象是Response类型的实例
       .subscribe(result => {      
           ...   
       }) 
    }
}

我有话说

1.当DI解析 Providers 时,都会对提供的每个 provider 进行规范化处理,即转换成标准的形式。

function _normalizeProviders(providers: Provider[], 
    res: Provider[]): Provider[] { 
    providers.forEach(b => {   
      if (b instanceof Type) { // 支持简洁的语法,转换为标准格式      
          res.push({provide: b, useClass: b});    
      } 
      else if (b && typeof b == 'object' && (b as any).provide !== undefined)
      {  
          res.push(b as NormalizedProvider);    
      } 
      else if (b instanceof Array) {   
          _normalizeProviders(b, res); // 如果是数组,进行递归处理   
      } else {     
           throw invalidProviderError(b);    
      }  
    });  
    
    return res;
}

2.创建 Token 时为了避免命名冲突,尽量避免使用字符串作为Token。

3.若要创建模块内通用的依赖对象,需要在 NgModule 中注册相关的 provider,若在每个组件中,都有唯一的依赖对象,就需要在 Component 中注册相关的 provider。

4.multi providers 的具体作用,具体请参考 - Angular2 Multi Providers

5.Provider 是用来描述与 Token 关联的依赖对象的创建方式。当我们使用 Token 向 DI 系统获取与之相关连的依赖对象时,DI 会根据已设置的创建方式,自动的创建依赖对象并返回给使用者。

Provider接口

export interface ClassProvider {  
// 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken
// 的实例或字符串  
    provide: any;   
    useClass: Type;  
    // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表 
     multi?: boolean; 
}

export interface ValueProvider {  
    provide: any;  
    useValue: any;  
    multi?: boolean;
} 

export interface ExistingProvider {  
    provide: any;  
    useExisting: any;  
    multi?: boolean;
} 

export interface FactoryProvider {  
    provide: any;  
    useFactory: Function;  
    deps?: any[];  // 用于设置工厂函数的依赖对象  
    multi?: boolean;
}

总结

在文章的最后,想举一个现实生活中的例子,帮助初学者更好地理解 Angular 2 DI 和 Provider。

Provider 中的 token 可以理解为菜名,useClass、useValue可以理解为菜的烹饪方式,而依赖对象就是我们所点的菜,而 DI 系统就是我们的厨师了。如果没有厨师,我们就得关心煮这道菜需要哪些原材料,怎么煮菜,重要的是还得自己煮,可想而知多麻烦。而有了厨师(DI),我们只要在菜谱上点菜,必要时备注一下烹饪方式,不过多久香喷喷的菜就上桌鸟~~~。


相关内容

热门资讯

瀚云通取得运动型线缆保护拖链专... 国家知识产权局信息显示,深圳市瀚云通科技有限公司取得一项名为“一种运动型线缆的保护拖链”的专利,授权...
第六届成渝双城青少年科技雏鹰研... 人民网重庆7月7日电 (记者胡虹)7月6日,由重庆市科协和成都市科协联合主办的第六届成渝双城青少年科...
三星Galaxy F70 Pr... IT之家 7 月 7 日消息,消息源 Mohammed Khatri 发文,透露三星旗下一款 Gal...
央媒关注!成都太空算力加速布局 7月6日,经济日报发布文章《太空算力加速布局》,其中关注成都构建从卫星制造到算力服务的全链条产业体系...
投资中国,与未来共舞——202... 7月8日下午,一场汇聚顶级资本力量与硬核科技创新力量的盛会——2026新京报贝壳财经年会未来大会 “...
美国恢复对伊朗石油制裁 根据美国财政部外国资产控制办公室当地时间7月7日消息,美国撤销一项授权允许伊朗石油销售的通用许可,相...
暗示要对梅洛尼下达限制令后,特... 当地时间7月7日,正在土耳其参加北约峰会的美国总统特朗普称意大利总理梅洛尼是“好人”,尽管他上周末曾...
广西近4000名被困师生欢呼:... 解放军来了!广西贵港高级中学近4000名师生被困,下午1点26分,解放军冲锋舟全速挺进救援现场,带着...
埃尔多安举行欢迎仪式,特朗普罕... 美国总统特朗普7月7日抵达土耳其首都安卡拉,参加即将在这里举行的北约峰会。当天,在土耳其总统埃尔多安...
纪念高善文:那个敢说真话、爱自... 对于无数投资者而言,高善文不仅是一位经济学家,更是中国证券研究行业从起步到成熟的见证者与塑造者。作者...