Frontend
October 15, 2023

Использование RxJS в Angular: основы реактивного программирования

Реактивное программирование - это подход к написанию кода, при котором данные представлены в виде потоков. Это значит, что когда данные в потоке меняются, все части программы, которые зависят от этих данных, автоматически обновляются.

Зачем использовать реактивное программирование в Angular?

Реактивный подход отлично подходит для Angular, потому что:

  • Приложения на Angular управляются данными и их изменениями. Реактивное программирование позволяет легко отслеживать изменения данных.
  • Можно строить приложения, которые реагируют на изменения данных в реальном времени. Например, обновлять интерфейс при получении данных с сервера.
  • Потоки данных проще тестировать и отлаживать.

Таким образом, реактивность делает Angular-приложения более гибкими и удобными в разработке.

RxJS: Основы и понятия

Что такое RxJS и зачем он нужен?

RxJS - это библиотека для реактивного программирования на JavaScript. Она позволяет создавать потоки данных и работать с ними.

RxJS дает нам:

  • Observable - наблюдаемые объекты, которые представляют потоки данных.
  • Операторы для фильтрации, преобразования, объединения потоков.
  • Инструменты для управления подпиской на потоки.

Таким образом, RxJS упрощает реактивную разработку в Angular.

Observable, Observer, Subscription - что это?

  • Observable - источник данных, который выдает последовательность значений во времени. Например, события клика или данные с сервера.
  • Observer - наблюдатель, который подписывается на Observable и реагирует на новые выданные значения.
  • Subscription - подписка, которая представляет связь между Observable и Observer. Она позволяет отписаться от потока данных.

Пример кода:

const stream$ = new Observable(observer => {
  observer.next('Hello');  
  observer.next('World');
});

const observer = {
  next: value => console.log(value)  
};

const subscription = stream$.subscribe(observer); 

// Выведет: 
// Hello 
// World

subscription.unsubscribe(); // отписываемся от потока

Работа с операторами

Операторы позволяют преобразовывать, фильтровать, объединять потоки данных. Например:

map - применяет функцию к каждому значению:

stream$.pipe(
  map(val => val * 2)  
);

filter - оставляет только значения, удовлетворяющие условию:

stream$.pipe(
  filter(val => val > 2)
);

merge - объединяет несколько потоков в один:

merge(
  streamA$, 
  streamB$
)

И многие другие.

Операторы являются основой реактивного программирования в RxJS.

Использование RxJS в Angular

Как подключить RxJS к проекту

RxJS уже включен в Angular из коробки. Для использования нужно импортировать необходимые операторы и классы.

Например:

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

Примеры использования RxJS в Angular

Давай рассмотрим примеры использования RxJS в компонентах Angular:

Обработка событий

Можно создать поток из событий click и подписаться на него:

const click$ = fromEvent(button, 'click');

click$.subscribe(() => {
  // обработка клика
});

Асинхронные HTTP запросы

HTTP запросы возвращают Observable. Мы можем применить операторы:

getUsers() {
  return this.http.get('/api/users')
    .pipe(
      map(response => response.users)  
    );
}

Управление состоянием

Состояние можно хранить в Observable и отслеживать изменения:

@Component({/*...*/})
export class UserComponent {

  user$ = new BehaviorSubject(null);
  
  constructor() {
    this.user$.subscribe(user => {
      // отображение измененного пользователя
    });
  }
  
  updateUser(user) {
    this.user$.next(user); 
  }

}

Практические примеры

Давай создадим простое реактивное приложение на Angular.

Пример 1: таймер обратного отсчета

Создадим компонент таймера, который будет показывать секунды в обратном порядке от 10 до 0.

Используем RxJS:

@Component({/*...*/})
export class TimerComponent {

  seconds$ = interval(1000).pipe(    
    map(val => 10 - val),
    take(10) 
  );

  constructor(){
    this.seconds$.subscribe(sec => {
      // отображаем секунды в шаблоне      
    });
  }

}

Объяснение:

  • interval создает поток, который выдает значения через заданный промежуток времени
  • map преобразует значения в отсчет от 10 до 0
  • take ограничивает поток 10 значениями
  • Подписываемся и отображаем секунды в шаблоне

Пример 2: поиск пользователей

Реализуем компонент поиска пользователей по имени.

HTML:

<input [(ngModel)]="username" (keyup)="search()">

<div *ngFor="let user of users$ | async">
  {{user.name}}
</div>

Компонент:

@Component({/*...*/})
export class UserSearchComponent {

  username = '';
  
  users$ = new BehaviorSubject([]);
  
  constructor(private http: HttpClient) {}

  search() {
    this.http.get('/api/users/?name=' + this.username)
      .subscribe(users => {
        this.users$.next(users);
      })
  }

}

Пояснение:

  • users$ хранит найденных пользователей
  • При вводе в input делаем запрос и обновляем users$
  • Асинхронно подписываемся на users$ в шаблоне и отображаем данные

Итог

В этой статье мы рассмотрели основы реактивного подхода в Angular с RxJS:

  • Observable и операторы для работы с потоками данных
  • Использование в компонентах для HTTP, событий, состояния
  • Практические примеры приложений

Я надеюсь, теперь ты лучше понимаешь как применять RxJS в Angular! Эти знания помогут тебе писать более реактивные и эффективные приложения.