Проблема области с использованием внедрения зависимостей массива поставщиков компонентов в Angular

#angular #dependency-injection

Вопрос:

Возможно ли предоставить услугу другой службе, используя массив поставщиков компонента?

Я попытался ввести службу таким образом, но не смог заставить ее работать.

Это компонент, в котором я предоставляю услугу.

 @Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [{ provide: EXAMPLE_TOKEN, useClass: ExampleService }]  <---- this doesn't work as expected
})
export class AppComponent {
}
 

Это компонент, который использует службу, в которую я пытаюсь ввести маркер, определенный выше.

 @Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
})
export class ExampleComponent {
  constructor(private parentService: ParentService) { }
}
 

Здесь я использую токен, определенный в компоненте приложения.

 @Injectable({ providedIn: 'root' })
export class ParentService {
  constructor(@Inject(EXAMPLE_TOKEN) private conf: ExampleService) { }  <---- throws error
}
 

Я пытаюсь найти способ предоставить услугу с точки зрения компонентов, не используя поставщиков модулей. Возможно ли этого достичь?

Ответ №1:

Это должно быть возможно сделать, но я полагаю, что это не работает, потому что вы предоставляете ParentService root инжектор (с providedIn: 'root' ). Если вы удалите это и ParentService разместите данные в providers массиве ExampleComponent , то ваша услуга будет предоставляться инжектором компонентов , и angular пройдет по дереву инжекторов компонентов вплоть до вашего AppComponent и решит ваши EXAMPLE_TOKEN проблемы оттуда. Если вы предоставляете услугу в root инжекторе, она будет пытаться разрешить зависимости только с помощью корневых и платформенных инжекторов.

Обслуживание:

 @Injectable()
export class ParentService {
  constructor(@Inject(EXAMPLE_TOKEN) private conf: ExampleService) { }
}
 

Компонент:

 @Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
  providers: [ParentService],
})
export class ExampleComponent {
  constructor(private parentService: ParentService) { }
}
 

Редактировать:

Angular пытается разрешить проблему ParentService на уровне инжектора элемента ( ExampleComponent ), затем перемещается по дереву вплоть до инжектора корневого элемента ( AppComponent ), но AppComponent не предоставляет ParentService . Затем он начинает обходить дерево инжектора модуля и находит ParentService его в root инжекторе. Но на этом уровне (уровень корневого инжектора) нет поставщика EXAMPLE_TOKEN , и поэтому инициализация завершается неудачно, и мой ответ помогает. В моем фрагменте кода Angular попытается использовать инжекторы элементов при создании ParentService , и он успешно найдет EXAMPLE_TOKEN зависимость в инжекторе корневого элемента.

Комментарии:

1. Спасибо вам за ответ. Однако есть кое-что, что не совсем ясно. Разве, как правило, «Элементные объекты» не просматриваются сначала, прежде чем пытаться разрешить «Модульные объекты»? Вы правильно подметили, но я не думаю, что это пока решает проблему. Или я ошибаюсь?

2. Вы правы, мне действительно удалось заставить его работать, большое спасибо.

3. @Razvan Пожалуйста, не обращайте внимания на мой предыдущий комментарий, я добавил некоторые дополнительные пояснения в сам ответ.