Для чего нужен декоратор Injectable при создании сервисов в Angular 6?

136

При создании сервисов в Angular CLI он добавляет дополнительные метаданные с помощью свойства «предоставлено в» со значением по умолчанию «root» для декоратора Injectable.

@Injectable({
  providedIn: 'root',
})

Что именно делает providedIn? Я предполагаю, что это делает службу доступной как одноэлементную службу «глобального» типа для всего приложения, однако было бы лучше объявить такие службы в массиве поставщиков AppModule?

ОБНОВИТЬ:

Для всех остальных следующий абзац также дает еще одно хорошее объяснение этого, в частности, если вы хотите предоставить свои услуги только функциональному модулю.

Теперь существует новый рекомендуемый способ регистрации провайдера непосредственно внутри @Injectable()декоратора с использованием нового providedIn атрибута. Он принимает 'root'в качестве значения любой модуль вашего приложения. Когда вы используете 'root', ваш injectableбудет зарегистрирован как синглтон в приложении, и вам не нужно добавлять его к поставщикам корневого модуля. Точно так же, если вы используете providedIn: UsersModule, то injectableрегистрируется как поставщик модуля, UsersModuleне добавляя его в providersмодуль. "- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

ОБНОВЛЕНИЕ 2:

После дальнейшего расследования я решил, что полезно иметь providedIn: 'root'

Если вы хотите provideиспользовать службу в любом модуле, кроме корневого, тогда вам лучше использовать providersмассив в декораторах функционального модуля, иначе вы столкнетесь с круговыми зависимостями. Здесь можно провести интересные обсуждения - https://github.com/angular/angular-cli/issues/10170

Стефан Звонар
источник
17
Я думаю, что ваши обновления должны быть ответом (вы можете отвечать на свои вопросы), а не добавлять его к своему вопросу.
PhoneixS
Самая важная часть - SINGLETON, о ней никто не упоминает!
Кайл Беркетт

Ответы:

55

если вы используете providedIn, инъекционный объект регистрируется как поставщик модуля без добавления его к поставщикам модуля.

Из Docs

Сама служба - это класс, созданный CLI и украшенный @Injectable. По умолчанию этот декоратор настроен с помощью свойства providedIn, которое создает поставщика для службы. В этом случае providedIn: 'root' указывает, что служба должна быть предоставлена ​​в корневом инжекторе.

Sajeetharan
источник
4
Спасибо Саджитаран. Ладно, похоже, это новый ярлык для указания того, где должна быть предоставлена ​​услуга. Я предполагаю, что вначале я предпочел бы смотреть на список поставщиков модуля, чтобы увидеть все сервисы, объявленные как поставщики, а не просматривать разрозненную базу кода для тегов ProvidedIn .... (?)
Стефан Звонар
2
Была ли у Angular какая-то причина добавить это? Есть проблема, которую это решает? Я не вижу причин для этого.
Prolink007 02
3
Удерживает определение AppModule / CoreModule немного меньше;)
Stefan Zvonar
22
@ prolink007. Использование providedIn позволяет приложению лениво загружать сервисы. Чтобы проверить это, поместите журналы консоли в свои службы. Моя домашняя страница раньше загружала 16 сервисов, а теперь загружает 9. Трудно количественно оценить производительность, но я чувствую себя лучше, зная, что я не загружаю сервисы, пока они не понадобятся :).
Stevethemacguy
3
Вы можете сделать дерево ваших сервисов встряхиваемым, используя providedInатрибут, чтобы определить, где сервис должен быть инициализирован при использовании @Injectable()декоратора. Затем вы должны удалить его из атрибута provider вашего NgModuleобъявления, а также из его оператора импорта. Это может помочь уменьшить размер пакета за счет удаления неиспользуемого кода из пакета.
nircraft 01
48

providedIn: 'root' это самый простой и эффективный способ предоставления услуг, начиная с Angular 6:

  1. Сервис будет доступен для всего приложения как синглтон без необходимости добавлять его в массив поставщиков модуля (например, Angular <= 5).
  2. Если служба используется только в ленивом загружаемом модуле, она будет лениво загружена с этим модулем.
  3. Если он никогда не используется, он не будет включен в сборку (дерево встряхнуто).

Для получения дополнительной информации прочтите документацию и ответы на часто задаваемые вопросы о NgModule.

Btw:

  1. Если вы не хотите использовать синглтон для всего приложения, используйте вместо этого массив компонента поставщика.
  2. Если вы хотите ограничить область видимости, чтобы никакой другой разработчик никогда не использовал вашу службу вне определенного модуля, используйте providersвместо этого массив NgModule.
Мик
источник
38

Из Документов

Что такое инъекционный декоратор?

Помечает класс как доступный для Injector для создания.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

Сама служба - это класс, созданный CLI и украшенный @Injectable ().

Что именно делает providedIn?

Определяет, какие инжекторы будут предоставлять инъекционный объект, либо связав его с @NgModule или другим InjectorType, либо указав, что этот инъекционный компонент должен быть предоставлен в «корневом» инжекторе, который будет инжектором уровня приложения в большинстве приложений.

providedIn: Type<any> | 'root' | null

providedIn: 'root'

Когда вы предоставляете сервис на корневом уровне, Angular создает единый общий экземпляр сервиса и внедряет его в любой класс, который его запрашивает. Регистрация поставщика в метаданных @Injectable () также позволяет Angular оптимизировать приложение, удаляя службу из скомпилированного приложения, если она не используется.

providedIn: Модуль

Также можно указать, что услуга должна предоставляться в конкретном @NgModule. Например, если вы не хотите, чтобы служба была доступна приложениям, если они не импортируют созданный вами модуль, вы можете указать, что служба должна быть предоставлена ​​в модуле.

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

@Injectable({
  providedIn: UserModule,
})
export class UserService {
}

Этот метод является предпочтительным, потому что он включает встряхивание дерева (встряхивание дерева - это шаг в процессе сборки, который удаляет неиспользуемый код из базы кода ) службы, если его ничего не внедряет.

Если невозможно указать в службе, какой модуль должен ее предоставлять, вы также можете объявить поставщика службы внутри модуля:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
источник
4
Лучшее объяснение.
nop
2
этот ответ лучше, чем определение в угловом документе. очень ясно.
Шамира Ануранга
2
Очень хорошо объяснено, большое спасибо!
Заки Мохаммед
А когда он пустой, например @Injectable()?
Бен Талиадорос,
13

providedIn сообщает Angular, что корневой инжектор отвечает за создание экземпляра вашего сервиса. Услуги, предоставляемые таким образом, автоматически становятся доступными для всего приложения, и их не нужно указывать в каком-либо модуле.

Классы обслуживания могут действовать как собственные поставщики, поэтому их определение в декораторе @Injectable - это все, что вам нужно.

Джавад Фаруки
источник
4

По данным Documentation:

Регистрация поставщика в метаданных @Injectable () также позволяет Angular оптимизировать приложение, удаляя службу из скомпилированного приложения, если она не используется.

Maarti
источник