Spec-Zone.ru › Angular

Создание и использование сервисов

Сервисы — это повторно используемые фрагменты кода, которыми можно пользоваться во всём приложении Angular. Обычно их используют для получения данных, реализации бизнес-логики и других функций, к которым нужен доступ нескольким компонентам.

Создание сервиса

Вы можете создать сервис с помощью Angular CLI следующей командой:

ng generate service CUSTOM_NAME

Эта команда создаёт отдельный файл CUSTOM_NAME.ts в каталоге src.

Вы также можете создать сервис вручную, добавив декоратор @Service() к классу TypeScript. Это сообщает Angular, что класс можно использовать как внедряемую зависимость.

В следующем примере определяется сервис, с помощью которого пользователи могут добавлять и получать данные:

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

@Service()
export class BasicDataStore {
  private data: string[] = [];

  addData(item: string): void {
    this.data.push(item);
  }

  getData(): string[] {
    return [...this.data];
  }
}

Как становятся доступны сервисы

Когда вы используете @Injectable({ providedIn: 'root' }) в сервисе, Angular:

  • Создаёт один экземпляр (синглтон) для всего приложения
  • Делает его доступным во всём приложении без дополнительной настройки
  • Выполняет tree-shaking, поэтому Angular добавляет сервис в пакет JavaScript, только если вы действительно его используете

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

Использование декоратора @Service

Для распространённого случая, когда синглтон-сервис доступен во всём приложении, Angular предоставляет декоратор @Service как более удобную альтернативу @Injectable({providedIn: 'root'}).

Приведённый выше пример BasicDataStore можно переписать с помощью @Service:

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

@Service()
export class BasicDataStore {
  private data: string[] = [];

  addData(item: string): void {
    this.data.push(item);
  }

  getData(): string[] {
    return [...this.data];
  }
}

Это работает так же, как и вариант с @Injectable({providedIn: 'root'}) выше: Angular создаёт один экземпляр, делает его доступным везде и удаляет его из пакета с помощью tree-shaking, если он никогда не внедряется.

Замена реализации фабрикой

Если вам нужно управлять созданием синглтона, например подставлять другую реализацию в зависимости от среды, передайте функцию factory.

Фабрика выполняется в контексте внедрения зависимостей, поэтому внутри неё можно использовать inject() для получения других зависимостей.

Следующий сервис Analytics локально ничего не делает, чтобы события не засоряли консоль во время разработки. В production-среде фабрика считывает токен ANALYTICS_ENABLED и возвращает подкласс GoogleAnalytics, который перенаправляет события реальному трекеру:

import {inject, InjectionToken, Service} from '@angular/core';
import {ANALYTICS_ENABLED} from './token';

@Service({
  factory: () => (inject(ANALYTICS_ENABLED) ? new GoogleAnalytics() : new Analytics()),
})
export class Analytics {
  track(event: string, payload?: Record<string, unknown>) {
    // No-op by default.
  }
}

class GoogleAnalytics extends Analytics {
  override track(event: string, payload?: Record<string, unknown>) {
    // Dispatches an analytics event to Google Analytics
  }
}

ПРИМЕЧАНИЕ: Параметр factory заменяет параметры useClass, useValue, useExisting и useFactory декоратора @Injectable. Если вам нужен какой-либо из них, продолжайте использовать @Injectable.

Отключение автоматического предоставления

По умолчанию @Service предоставляет класс в корневом инъекторе. Если вы хотите предоставлять его вручную, например ограничить его областью действия определённого маршрута или компонента, задайте autoProvided: false:

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

@Service({autoProvided: false})
export class AnalyticsLogger {
  trackEvent(name: string) {
    console.log('event:', name);
  }
}

В этом случае вам нужно самостоятельно добавить сервис в массив providers, как и обычный @Injectable():

Когда использовать @Service, а когда @Injectable

Используйте @Service, когда создаёте новый класс-синглтон, который использует inject() для своих зависимостей. Продолжайте использовать @Injectable, если вам нужно что-либо из следующего:

  • Внедрение зависимостей через конструктор. @Service поддерживает только функцию inject().
  • Расширенная настройка провайдера, например useClass, useValue, useExisting или useFactory. @Service предоставляет вместо них один параметр factory.
  • Области действия, отличные от корневой, например providedIn: 'platform'.

Внедрение сервиса

Создав сервис с помощью providedIn: 'root', вы можете внедрить его в любом месте приложения с помощью функции inject() из @angular/core.

Внедрение в компонент

import {Component, inject} from '@angular/core';
import {BasicDataStore} from './basic-data-store';

@Component({
  selector: 'app-example',
  template: `
    <div>
      <p>{{ dataStore.getData() }}</p>
      <button (click)="dataStore.addData('More data')">Add more data</button>
    </div>
  `,
})
export class Example {
  dataStore = inject(BasicDataStore);
}

Внедрение в другой сервис

import {inject, Service} from '@angular/core';
import {AdvancedDataStore} from './advanced-data-store';

@Service()
export class BasicDataStore {
  private advancedDataStore = inject(AdvancedDataStore);
  private data: string[] = [];

  addData(item: string): void {
    this.data.push(item);
  }

  getData(): string[] {
    return [...this.data, ...this.advancedDataStore.getData()];
  }
}

Дальнейшие шаги

Хотя providedIn: 'root' подходит для большинства случаев, Angular также предлагает дополнительные способы настройки сервисов для более специализированных сценариев:

  • Экземпляры для отдельных компонентов — когда компонентам нужны собственные изолированные экземпляры сервиса
  • Ручная настройка — для сервисов, требующих настройки во время выполнения
  • Фабричные провайдеры — для динамического создания сервисов в зависимости от условий во время выполнения
  • Провайдеры значений — для предоставления объектов конфигурации или констант

Подробнее об этих расширенных шаблонах можно узнать в следующем руководстве: определение провайдеров зависимостей.

Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/di/creating-and-using-services

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API