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;
}
}
);
}
}

Таким образом, на основании переданного id меняется состояние компонента, в котором реализуется наблюдение за observable.

Редактировать на GitHub