#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 Пожалуйста, не обращайте внимания на мой предыдущий комментарий, я добавил некоторые дополнительные пояснения в сам ответ.