首页 > 解决方案 > Angular向子模块注入不同的服务实现

问题描述

我有一个实现 ErrorHandler 的类,并在根级别提供。我的应用程序中有 3 个模块,其中 2 个可以在根级别使用 ErrorHandler,但其中一个应该有不同版本的 ErrorHandler。

我已经尝试创建 ErrorHandler 的两个实现,其中一个在根级别提供,我用 {providedIn: ThreePageModule} 装饰了第二个服务,但这似乎不像每当出现错误时那样工作:HttpErrorResponse 根级别ErrorHandler 开始了。我查看了角度文档,它说当子模块延迟加载时,它会获得提供的服务。我在这里错过了什么吗?

下面是 app.module.ts

@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
FormsModule,
BrowserModule,
HttpClientModule,
AppRoutingModule
],
providers: [
 ....other services...
{
  provide: HTTP_INTERCEPTORS,
  useClass: HttpConfigInterceptor,
  multi: true
},
{ provide: ErrorHandler, useClass: ExceptionHandlerService },
],
bootstrap: [AppComponent]
})
export class AppModule {}

AppRoutingModule.ts:

@NgModule({
imports: [
 RouterModule.forRoot(appRoutes)
],
exports: [
 RouterModule
]
})
export class AppRoutingModule { }

appRoutes.ts:

 export const appRoutes: Routes = [
   {
    path: 'one',
    loadChildren: './../one/one.module#OnePageModule'
 },
  {
      path: 'two',
      loadChildren: './../two/two.module#TwosPageModule'
  },
  {
    path: 'three',
    loadChildren: './../three/three.module#ThreePageModule'
  }
 ];

三模块.ts

@NgModule({
imports: [
 ...Imports...
],
entryComponents: [
 ThreeComponent
],
providers: [DatePipe],
declarations: [
....Declarations.....
]
})
export class ClaimsPageModule { }

ThreeErrorHandlerService.ts

@Injectable({
  providedIn: ThreePageModule
})
export class ThreeErrorHandlerService implements ErrorHandler {

constructor() { }

handleError(error: Error | HttpErrorResponse): void {
  if (error instanceof HttpErrorResponse) {
   return;
  }
 }
}

我想要的是在 ThreePageModule 中使用 ThreeErrorHandlerService,同时在其余两个模块中仍然使用 ExceptionHandlerService。

这是我们实现它的方式还是我做错了。

标签: angulardependency-injection

解决方案


我认为有一种方法可以实现这一目标。

app.tokens.ts


export function errorHandlerFactory (r: Router): AbstractErrorHandler {
  return r.url === '/foo' ? new ErrorHandlerThree('foo error!') : new ErrorHandlerOne('not foo !!')
}

export abstract class AbstractErrorHandler {
  abstract getCrtErr: () => string;
}

export class ErrorHandlerOne implements AbstractErrorHandler {
  constructor (public crtErr: string) { }

  getCrtErr () { return 'err!' }
}

export class ErrorHandlerThree implements AbstractErrorHandler {
  constructor (public crtErr: string) { }

  getCrtErr () { return 'err!' }
}

app.module.ts

@Component({
  selector: 'my-app',
  template: `
    <button [routerLink]="'foo'">foo route</button>

    <router-outlet></router-outlet>
  `,
})
class AppComponent {
  constructor (err: AbstractErrorHandler) {
    console.log(err) // not foo !!
  }
}

const routes: Routes = [
  { path: 'foo', loadChildren: () => import('./foo/foo.module').then(m => m.FooModule,) },
]

@NgModule({
  imports: [
    BrowserModule,
    RouterModule.forRoot(routes),
  ],
  declarations: [
    AppComponent
  ],
  providers: [
    { provide: AbstractErrorHandler, useFactory: errorHandlerFactory, deps: [Router] }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

foo.module.ts

@Component({
  selector: 'foo-comp',
  template: `this is foo!`,
})
export class FooComp {
  constructor (err: AbstractErrorHandler) {
    console.log('foo', err) // foo error!
  }
}

const routes: Routes = [
  { path: '', component: FooComp, }
]

@NgModule({
  declarations: [FooComp],
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
  ],
  providers: [
    { provide: AbstractErrorHandler, useFactory: errorHandlerFactory, deps: [Router] }
  ],

请注意,您可能需要在内部跟踪类实例,app.tokens.ts因为您可能不希望每次组件注入您的 this 依赖项时都需要一个新实例。

工厂提供者

ng-运行演示


推荐阅读