首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建可配置的服务角4

如何创建可配置的服务角4
EN

Stack Overflow用户
提问于 2017-07-03 01:22:51
回答 1查看 1.9K关注 0票数 6

我想创建一个服务,以便在几个角度应用程序中重复使用。

我用的是角克莱。

我希望服务是可配置的。换句话说,让每个应用程序能够使用不同的配置参数实例化服务,使用DI。

服务将位于共享库中,因此不能从父应用程序导入特定的文件路径以获取配置参数,必须通过DI获取它们。

我试着遵循这里的说明,因为这篇文章准确地描述了我面临的问题,但是我得到了一个错误:

代码语言:javascript
复制
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:

代码语言:javascript
复制
zone.js:643 Unhandled Promise rejection: No provider for String! ; Zone: <root> ; Task: Promise.then ; Value: Error: No provider for String!

这是我的相关代码:

main.ts:

代码语言:javascript
复制
...
import { provideAuthService } from 'shared-library';
...
platformBrowserDynamic().bootstrapModule(AppModule, [provideAuthService('Good Day')]);

app.module.ts:

代码语言:javascript
复制
...
import { AuthService } from 'shared-library';

@NgModule({
  declarations: [
      ...
  ],
  imports: [
    ...
  ],
  providers: [
    AuthService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

和auth.service.ts:

代码语言:javascript
复制
...

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') {
       ...
    }
}

提前感谢任何有能力在这里帮忙的人!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-03 01:42:53

您可以遵循由角路由器完成的模式,其中将配置对象定义为可注入对象,并且只能在主应用程序的模块中声明一次。

定义一个新的令牌来标识config对象:

代码语言:javascript
复制
export const APP_CONFIG = new InjectionToken<string>('AppConfig');

创建配置对象可以使用的接口或抽象类。这只会使维护配置对象变得更容易。这里有一个示例,但是您可以根据需要定义自己的属性或方法。

代码语言:javascript
复制
export interface AppConfig {
     name: string;
     baseUrl: string;
}

创建一个新模块来保存可配置的服务。这个模块将有一个forRoot()方法,允许您设置配置对象。它还将进行一次安全检查,以确保模块只配置一次,这是正确的(通过构造函数)。

代码语言:javascript
复制
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.');
         }
    }
}

然后,可以将config对象插入到服务类中。

代码语言:javascript
复制
@Injectable()
export class YourServiceClass {
     public constructor(@Inject(APP_CONFIG) config: AppConfig) {
     }
}

要配置服务,您必须在主模块中使用forRoot方法。

代码语言:javascript
复制
@NgModule({
    imports: [
        ServiceModule.forRoot({
             name: 'FooBar',
             baseUrl: 'http://www.example.com/'
        })
    ]
})
export class MainModule {}

因此,这里发生的事情是forRoot方法手动创建模块元数据。有一个令牌APP_CONFIG在任何地方都没有声明。因此,forRoot返回的模块声明它引用了传递给函数的一个特定值。

订单或模块导入变得非常重要,因为如果一个模块在主模块之前导入ServiceModule,那么APP_CONFIG将是未定义的。因此,我们在模块构造函数中检查这种情况。如果可以注入ServiceModule,那么它已经被导入了。这增加了一个限制,即只能使用模块的一个实例,也就是为服务配置的实例。

这是一个很好的模式,我使用这个模式,但是我遇到了一些延迟加载模块想要加载ServiceModule的情况。因此,如果你想避免头痛在项目的后面。尝试将您的可配置服务限制为模块中的唯一提供程序。一旦您开始向模块添加其他内容,您就更有可能需要在加载顺序上具有灵活性。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44876617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档