当前位置: 首页 > Web前端 > HTML

AngularInjectionTokenAPP_INITIALIZERmultiflag取值不同的讨论

时间:2023-03-28 19:33:37 HTML

下图是SAP电商云SpartacusUI中SiteContext处理逻辑相关的一段代码:exportconstcontextServiceProviders:Provider[]=[BaseSiteService,LanguageService,CurrencyService,{provide:APP_INITIALIZER,useFactory:initializeContext,deps:[ConfigInitializerService,SiteContextRoutesHandler],multi:true,},];注意第40行的flag,multi,默认值为false,表示代码实现后注册的initializer,会覆盖先注册的initializerprovider实现。也就是说,在这种情况下,APP_INITIALIZER只能有一个提供者。如果设置了multi:true,新的提供者将被添加到之前注册的提供者中,使一个代币拥有多个提供者。Angular会在调用此令牌时执行所有这些令牌。[外链图片传输失败,源站可能有防盗链机制,建议保存图片直接上传(img-t9CQg0dA-1657529948839)(https://upload-images.jianshu...)]因此,开发者可以使用multi:true来创建多个Providertoken。这意味着我们可以创建多个函数/服务并在初始化期间调用它。要进行测试,请创建初始化程序的两个实现:setTimeout(()=>{console.log(`initializeApp2Finished`);resolve();},2000);});};}然后使用multi:true为同一个注入令牌APP_INITIALIZER注册两个不同的供应商:useFactory:initializeApp2,multi:true}],最后运行时,这两个初始化器会同时触发。此外,此示例使用useFactory为InjectionToken注册提供程序。一个例子:constWINDOW=newInjectionToken('Areferencetothewindowobject',{factory:()=>window,});在上面的示例中,使用工厂函数作为提供者来设置InjectionToken,就好像它是在应用程序的根注入器中明确定义的一样。现在我们可以在应用程序的任何地方使用它:@Component({selector:'my-app'})exportclassAppComponent{constructor(@Inject(WINDOW)window:Window){}}我们可以使用注入函数,在工厂功能的执行环境,以获取对其他提供者的引用。让我们看另一个例子:import{inject,InjectionToken}from'@angular/core';从'@angular/router'导入{ActivatedRoute};导出类型TimespanProvider=Observable;exportconstTIMESPAN=newInjectionToken('订阅时间跨度查询参数',{factory(){constactivatedRoute=inject(ActivatedRoute);returnactivatedRoute.queryParams.pipe(pluck('timespan'),filterNil(),distinctUntilChanged());},});上面的例子,我们注入ActivatedRoute,使用inject获取它的provider实例,为timespan查询参数返回一个observable。将Observable导出到一个新的类型别名:TimespanProvider。这个InjectionToken的注入例子:@Component({selector:'app-home'})exportclassHomeComponentimplementsOnInit{constructor(@Inject(TIMESPAN)privatetimespan$:TimespanProvider){}ngOnInit(){this.timespan$.pipe(untilDestroyed(this)).subscribe(console.log);}}另一个例子:我们有一个ThemeService实现类,暴露了用户当前的Theme值:@Injectable({providedIn:'root'})exportclassThemeService{privatetheme=newSubject<字符串>();主题$=this.theme.asObservable();setTheme(主题:字符串){this.theme.next(主题);}}Component读取当前Theme的值:@Component({selector:'app-hello',template:`

{{theme$|async}}

`})exportclassHelloComponent{theme$:可观察<字符串>;构造函数(私人主题服务:ThemeService){}ngOnInit(){this.theme$=this.themeService.theme$;InjectionToken的实现:exporttypeActiveThemeProvider=Observable;exportconstACTIVE_THEME=newInjectionToken('活动主题',{factory(){returninject(ThemeService).theme$;}});先定义一个新的Type,然后使用工厂方法返回Observable类型的结果