Subject
Класс Subject
импортируется из rxjs/Subject
. Данный класс объединяет observable
и observer
в одном объекте. Он реализует следующие методы:
next()
для отправки данных используется метод.subscribe()
для принятия данных метод.unsubscribe()
для отписки.
Хорошей практикой является реализовать сервис на основе Subject
и использовать его как альтернативу Emit
.
Рассмотрим пример создания простого сервиса на основе класса Subject
и то как его можно использования в различных компонентах. Один из компонентов будет реализовывать метод next()
, для формирования потока. Второй компонент будет наблюдать и реагировать на изменения данного потока.
Для начала создадим сервис UsersService
в файле \app\users.service.ts
:
import { Subject } from 'rxjs/Subject';
export class UsersService {
userActivated = new Subject();
}
Затем, нам нужно зарегистровать этот сервис в провайдерах app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { UserComponent } from './user/user.component';
import { AppRoutingModule } from './app-routing.module';
import { UsersService } from './users.service';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
UserComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [UsersService], // имя сервиса нужно передать в массив ключа providers
bootstrap: [AppComponent]
})
export class AppModule { }
В шаблоне observable
компонента поставим обработчик на событие click
для запуска метода onActivate()
:
<p>User with <strong>ID {{ id }}</strong> was loaded</p>
<button class="btn btn-primary" (click)="onActivate()">Activate!</button>
Метод onActivate()
использует метод next()
для формирования потока:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { UsersService } from '../users.service';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
id: number;
constructor(private route: ActivatedRoute, private usersService: UsersService) { }
//...
onActivate() {
this.usersService.userActivated.next(this.id);
}
}
И наконец, так выглядит подписка в компоненте реализующем наблюдателя:
import { Component, OnInit } from '@angular/core';
import { UsersService } from './users.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
user1Activated = false;
user2Activated = false;
constructor(private usersService: UsersService) {}
ngOnInit() {
this.usersService.userActivated.subscribe(
(id: number) => {
if (id === 1) {
this.user1Activated = true;
} else if (id === 2) {
this.user2Activated = true;
}
}
);
}
}