Angular 2 useExisting провайдеры

7

Каковы условия использования useExisting поставщика?

Это useExistingOrThrowIfThereIsNone или useExistingOrCreateIfThereIsNone? Можно ли каким-либо образом изменить это поведение в зависимости от наших потребностей? Если один из них не поддерживается, может ли эмулироваться неподдерживаемый?

Документация полностью неясна и просто дает пример, что useExisting может повторно использовать экземпляр из useClass.

Теги:
angular
angular2-services

3 ответа

14
Лучший ответ

В этом примере

providers: [
    A, 
    {provide: B, useClass: A}, 
    {provide: C, useExisting: A}]

Если у вас

constructor(private a: A)

создается экземпляр для первого поставщика.

constructor(private b: B)

создается экземпляр для второго провайдера

constructor(private c: C)

вводится экземпляр первого провайдера.

Если вы начинаете с

constructor(private c: C)

создается экземпляр для первого поставщика и вводится

  • 0
    useExisting похоже на псевдоним другого провайдера. useClass - это просто новый поставщик, который отображает запрошенный тип на фактический тип, а ключ - запрошенный тип.
  • 0
    Вам не нужно ничего делать, чтобы сделать Service единичным везде, кроме как просто предоставить его один раз в корневом компоненте. DI Angular2 поддерживает один экземпляр для каждого поставщика. Если вы предоставите его только один раз, будет только один экземпляр.
Показать ещё 2 комментария
2

Когда мы пишем {provide: A, useClass: B}, Angular создаст карту между токеном A и классом B.

Когда мы пишем {provide: A, useExisting: B}, Angular создаст карту между токеном A и токеном B.

Разница между этими картами:

  • токен A → экземпляр класса B
  • токен A → токен B → экземпляр некоторого класса для токена B
1

Просто небольшое добавление/разъяснение к ответу @GünterZöchbauer.

На самом деле он используетExistingOrThrowIfThereIsNone, когда мы говорим о токенах. useExisting создает псевдоним для другого токена, а не экземпляра, поэтому должен быть маркером, указанным useExisting, иначе будет выбрано исключение. Но когда мы говорим о экземплярах, он будет работать до тех пор, пока последний токен в цепочках регистрируется экземпляр, поэтому в этом смысле используетсяExistingOrCreateIfThereIsNone.

Рассмотрим это:

// T = token, I = instance
providers: [
    {provide: B, useClass: A}, // T[B] => I[A]
    {provide: C, useExisting: A}] // T[C] => ??? - there no T[A] declared

...
constructor(private a: B) {} // works
...
constructor(private a: C) {} // throws an exception: 

В этом случае второе объявление будет вызывать ошибку, потому что токен C ссылается на токен A, но нет токена. Объявлено где угодно, даже хотя в инжекторе есть класс класса A. Angular не будет пытаться создать экземпляр A для токена C или связать токен с существующим экземпляром. Я просто случайно подтвердил это в одном из моих проектов.:)

Следующие действия будут работать, хотя из-за причин, хорошо описанных в других ответах:

providers: [
    {provide: B, useClass: A}, // T[B] => I[A]
    {provide: C, useExisting: B}] // T[C] => T[B] => I[A]

...

constructor(private a: B) {} // works
...
constructor(private a: C) {} // works

В этом примере экземпляр для A будет создан для токена C, даже если не было экземпляра A, созданного ранее для токена B. Итак, для токена C это "использовать любой экземпляр для токена B", а для token B это "использовать существующий экземпляр A или создать новый, если он не существует".

  • 0
    Отличный пример, столкнулся с тем же сценарием проблемы

Ещё вопросы

Сообщество Overcoder
Наверх
Меню