首页 > 解决方案 > 一个组件具有相同服务的两个实例

问题描述

我有一个查询构建器服务,我想在一个组件中使用它两次。这可以做到吗?我曾尝试两次注入服务,但这似乎不起作用,因为服务只是相互引用,如下所示:

@Component({
  selector: 'app-manage-users',
  templateUrl: './manage-users.component.html',
  styleUrls: ['./manage-users.component.scss'],
  providers: [UserManagementQueryBuilderProvider]
})
export class ManageUsersComponent implements OnInit {

  public constructor(
    private readonly queryBuilder: QueryBuilderService,
    private readonly qb: QueryBuilderService
  ) { }

  public ngOnInit() {
    this.queryBuilder.table('users');
    console.log(this.qb['_table']); // Outputs "users"; expecting an empty string.
  }
}

我不确定这是否是因为我的提供程序是如何设置的(也就是多选项),但它看起来像这样:

export const UserManagementQueryBuilderProvider: Provider = {
  useFactory: (httpClient: HttpClient) => new QueryBuilderService(httpClient)
    .connection(environment.USER_MANAGEMENT_API),
  provide: QueryBuilderService,
  deps: [HttpClient],
  multi: false
};

如果我设置multitrue,我会收到一条错误消息,指出该表不是函数。

ERROR 错误:未捕获(承诺):TypeError:this.queryBuilder.table 不是函数

然后QueryBuilderService看起来像这样:

@Injectable({ providedIn: 'root' })
export abstract class GraphQLClientService {
  public constructor(
    private readonly httpClient: HttpClient
  ) { }
}


@Injectable()
export class QueryBuilderService extends GraphQLClientService { }

标签: javascriptangulartypescript

解决方案


Alias providers:
The useExisting provider key lets you map one token to another. In effect, the first token is an alias for the service associated with the second token, creating two ways to access the same service object. (Angular Docs)

Consider providing two InjectionTokens with UseExisting set to false, this way two different instances of QueryBuilderService will be injected, as demonstrated below:

import { Component, InjectionToken, Inject } from '@angular/core';

const QueryBuilder1 = new InjectionToken("QB1")
const QueryBuilder2 = new InjectionToken("QB2")

@Component({
  providers: [
    {
      provide: QueryBuilder1,
      useClass: QueryBuilderService,
      useExisting: false
    },
    {
      provide: QueryBuilder2,
      useClass: QueryBuilderService,
      useExisting: false
    }
  ]
})
export class ManageUsersComponent {

  public constructor(
    @Inject(QueryBuilder1) private queryBuilder1: QueryBuilderService,
    @Inject(QueryBuilder2) private queryBuilder2: QueryBuilderService
  ) { }

}

推荐阅读