【问题标题】:Is there a way to dynamically set mockedservices in the AppModule's providers?有没有办法在 AppModule 的提供程序中动态设置模拟服务?
【发布时间】:2020-02-09 09:48:22
【问题描述】:

我的 AppModule 定义有一个非常简单的设计。我的提供程序中有一组模拟服务,它利用本地数据,直到我的端点可以得到解决。随着服务端点的建立,我正在慢慢地将它们迁移过来。问题是应用程序非常需要一些配置来启动和运行端点,所以我创建了一个简单的配置文件,该文件创建了一个属性:useMockedServices,供想要使用演示的人使用。

{
  useMockedServices: true
}

但是,我的问题是。如何为提供者考虑此配置?

...
providers: [
  {provide: UserService, useClass: MockUserService},
  ...
],
...

我可以这样做吗:

providers: [
  { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: false }},
  ...
].concat( config.useMockedServices ? [
  {provide: UserSerice, useValue: MockUserService},
  ...
]: [],

我试图这样做,但我得到一个错误:没有重载匹配这个调用,它说“属性切片的类型不兼容”

providers: [
    // Default Options for using Modals / Dialogs.
    { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: false } },
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
    { provide: AuthGuard, useClass: AuthGuard },
    { provide: AuthenticationService, useClass: AuthenticationService }
  ].concat(
    configuration.useMockServices === true ? [
    { provide: UserService, useClass: MockUserService },
    ...
    ] : []
  ),
...

【问题讨论】:

  • @yazantahhan 这个答案的实施可能有效,但它不可持续。我有 15 个服务,每个服务都需要自己的功能。我认为有更好的方法。如果它是 1-off 服务,我会认为这是一个答案,但考虑到批量需求,我不会。

标签: angular typescript


【解决方案1】:

您可以使用useFactory 来做到这一点:

function userServiceFactory() {
   return enviroment.useMockedServices ? UserServiceMock : UserService;
}


...

providers: [
  {provide: UserService, useFactory: userServiceFactory},
  ...
]

或者,如果您将配置投入使用。

function userServiceFactory(config: ConfigService) {
   return config.useMockedServices ? UserServiceMock : UserService;
}


...

providers: [
  {provide: UserService, useFactory: userServiceFactory, deps:[ConfigService]},
  ...
]

【讨论】:

  • 正如cmets中所讨论的,要求是为每个函数创建一个工厂,这并不理想。我不喜欢这样,这是一个答案,但它并不是我正在寻找的通用解决方案,因为我的目标是在没有提供默认值的情况下只使用默认值。
  • 从现在开始没有通用的解决方案,依赖注入是静态的,webpack需要导入来连接javascript模块。你输的比赢的多。您可以使用通用工厂并将 window[serviceName + 'Mock'] 添加为字符串,但您 lint 会抛出一个错误,即您有真正正在导入的未使用的导入,并且可能会导致摇树失败。
  • 我不想添加明确的定义来做:{provide: UserService, useClass:UserService},因为这似乎是不必要的。不过,我可以轻松地做这样的事情:{provide: UserService, useClass: config.useMockedServices === true ? MockUserService: UserService },我只是希望有一种方法可以包含提供,如果我没有主动更改它,因为它只是分配 self 到 self 在我的示例中。
猜你喜欢
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 1970-01-01
  • 2014-06-04
相关资源
最近更新 更多