如何创建可配置服务Angular 4
我想创建一个服务,以便在几个角度应用程序中重复使用.
我正在使用angular-cli. 我希望服务是可配置的.换句话说,使用DI为每个应用程序提供使用不同配置参数实例化服务的能力. 该服务将位于共享库中,因此无法从父应用程序导入特定文件路径以获取配置参数,它必须通过DI获取它们. 我尝试按照说明here,因为文章描述了我面临的问题,但是我收到了一个错误: ERROR Error: No provider for String! at injectionError (core.es5.js:1169) at noProviderError (core.es5.js:1207) at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._throwOrNull (core.es5.js:2649) at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKeyDefault (core.es5.js:2688) at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKey (core.es5.js:2620) at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_.get (core.es5.js:2489) at resolveNgModuleDep (core.es5.js:9533) at _createClass (core.es5.js:9572) at _createProviderInstance$1 (core.es5.js:9544) at resolveNgModuleDep (core.es5.js:9529) 另外,来自zone.js: zone.js:643 Unhandled Promise rejection: No provider for String! ; Zone: <root> ; Task: Promise.then ; Value: Error: No provider for String! 这是我的相关代码: main.ts: ... import { provideAuthService } from 'shared-library'; ... platformBrowserDynamic().bootstrapModule(AppModule,[provideAuthService('Good Day')]); app.module.ts: ... import { AuthService } from 'shared-library'; @NgModule({ declarations: [ ... ],imports: [ ... ],providers: [ AuthService ],bootstrap: [AppComponent] }) export class AppModule { } 和auth.service.ts: ... export function provideAuthService(settings:string) { return { provide: AuthService,useFactory: () => new AuthService(settings) } @Injectable() export class AuthService { mgr: UserManager = new UserManager(this.settings); constructor(private settings:string='Hello') { ... } } 提前感谢任何可能在这里提供帮助的人! 解决方法
您可以遵循Angular路由器完成的模式,其中配置对象被定义为可注入,您只能在主应用程序的模块中声明一次.
定义新标记以标识配置对象: export const APP_CONFIG = new InjectionToken<string>('AppConfig'); 创建配置对象可以使用的接口或抽象类.这样可以更轻松地维护配置对象.这是一个示例,但您可以根据需要定义自己的属性或方法. export interface AppConfig { name: string; baseUrl: string; } 创建一个新模块以保存可配置服务.该模块将有一个forRoot()方法,允许您设置配置对象.它还将进行安全检查,以确保模块仅配置一次(通过构造函数). import { Injectable,NgModule,SkipSelf,Optional } from '@angular/core'; @NgModule({ providers: [ YourServiceClass ] }) export class ServiceModule { public static forRoot(config: AppConfig) { return { ngModule: ServiceModule,providers: [ {provide: APP_CONFIG,useValue: config} ] }; } public constructor(@Optional() @SkipSelf() parentModule: ServiceModule) { if(parentModule) { throw new Error('ServiceModule has already been imported.'); } } } 然后,您可以将配置对象注入服务类. @Injectable() export class YourServiceClass { public constructor(@Inject(APP_CONFIG) config: AppConfig) { } } 要配置服务,您必须在主模块中使用forRoot方法. @NgModule({ imports: [ ServiceModule.forRoot({ name: 'FooBar',baseUrl: 'http://www.example.com/' }) ] }) export class MainModule {} 那么这里发生的是forRoot方法手动创建模块元数据.有一个令牌APP_CONFIG尚未在任何地方声明.因此,forRoot返回的模块声明它引用了传递给函数的特定值. 订单或模块导入变得很重要,因为如果模块在主模块之前导入ServiceModule,则APP_CONFIG将是未定义的.因此,我们在模块构造函数中检查这种情况.如果可以注入ServiceModule,那么它已经被导入了.这增加了一个限制,即只能使用模块的一个实例,而这是为服务配置的实例. 这是一个很好的模式,我使用这种模式,但我遇到了延迟加载的模块想要加载ServiceModule的情况.所以,如果你想在项目后期避免头痛.尝试将可配置服务限制为模块中的唯一提供者.一旦开始向模块添加其他内容,您就更有可能需要在加载顺序中具有灵活性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |