Перейти к содержанию

Опциональные сервисы

Сервис может быть опциональным, необязательным. Например, в прошлой теме был создан сервис LogService:

1
2
3
4
5
export class LogService {
    write(logMessage: string) {
        console.log(logMessage);
    }
}

И был другой сервис DataService, который использовал LogService:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import { Injectable } from '@angular/core';
import { LogService } from './log.service';

@Injectable()
export class DataService {
    private data: string[] = [
        'Apple iPhone XR',
        'Samsung Galaxy S9',
        'Nokia 9',
    ];
    constructor(private logService: LogService) {}

    getData(): string[] {
        this.logService.write('операция получения данных');
        return this.data;
    }
    addData(name: string) {
        this.data.push(name);
        this.logService.write('операция добавления данных');
    }
}

Допустим, по какой-то причине сервис LogService не доступен для инжектирования, например, мы не добавили в провайдеры компонента AppComponent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
    selector: 'my-app',
    template: `
        <div>
            <div>
                <input
                    [(ngModel)]="name"
                    placeholder="Модель"
                />
                <button (click)="addItem(name)">
                    Добавить
                </button>
            </div>
            <table>
                <tr *ngFor="let item of items">
                    <td>{{ item }}</td>
                </tr>
            </table>
        </div>
    `,
    providers: [DataService], // Добавлен только сервис DataService
})
export class AppComponent {
    items: string[] = [];
    constructor(private dataService: DataService) {}

    addItem(name: string) {
        this.dataService.addData(name);
    }
    ngOnInit() {
        this.items = this.dataService.getData();
    }
}

Если мы запустим приложение, то в этом случае мы получим ошибку. Так как для сервиса LogService не определен провайдер. В этом случае мы можем определить сервис LogService как опциональный, применяя декоратор Optional. Для этого изменим код DataService:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { Injectable, Optional } from '@angular/core';
import { LogService } from './log.service';

@Injectable()
export class DataService {
    private data: string[] = [
        'Apple iPhone XR',
        'Samsung Galaxy S9',
        'Nokia 9',
    ];
    constructor(
        @Optional() private logService: LogService
    ) {}

    getData(): string[] {
        if (this.logService)
            this.logService.write(
                'операция получения данных'
            );
        return this.data;
    }
    addData(name: string) {
        this.data.push(name);
        if (this.logService)
            this.logService.write(
                'операция добавления данных'
            );
    }
}

Итак, в конструкторе класса мы получаем сервис как опциональный:

1
constructor(@Optional() private logService: LogService){}

Далее при обращении к сервису мы можем проверить, установлен ли он, и если он установлен, использовать его:

1
2
if (this.logService)
    this.logService.write('операция получения данных');

Комментарии