← Назад к вопросам

В чем разница между Observable и Subject?

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Observable и Subject в RxJS

Observable и Subject - это два ключевых концепта в RxJS (Reactive Extensions for JavaScript). Хотя они похожи на первый взгляд, они имеют принципиально разные роли. Давайте разберемся в их различиях и правильном использовании.

Observable

Observable - это объект, который представляет поток данных, которые могут быть эмитированы со временем. Это холодный источник данных, что означает, что каждый subscriber получает свой собственный поток значений.

import { Observable } from "rxjs";

// Создание Observable
const myObservable = new Observable((subscriber) => {
  console.log("Начало выполнения Observable");
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
});

// Каждый subscriber инициирует выполнение
const subscription1 = myObservable.subscribe({
  next: (value) => console.log("Подписчик 1:", value),
  complete: () => console.log("Подписчик 1 завершен")
});

const subscription2 = myObservable.subscribe({
  next: (value) => console.log("Подписчик 2:", value),
  complete: () => console.log("Подписчик 2 завершен")
});

// Вывод:
// Начало выполнения Observable
// Подписчик 1: 1
// Подписчик 1: 2
// Подписчик 1: 3
// Подписчик 1 завершен
// Начало выполнения Observable
// Подписчик 2: 1
// Подписчик 2: 2
// Подписчик 2: 3
// Подписчик 2 завершен

Характеристики Observable

1. Холодный поток (Cold)

  • Выполнение начинается только при подписке
  • Каждый subscriber получает независимую последовательность
  • Ленивое вычисление

2. Однонаправленный

  • Данные идут от источника к subscriber
  • Subscriber не может отправить данные обратно

3. Логирование и отладка

  • Фиксированный поток, который воспроизводится для каждого subscriber

Subject

Subject - это одновременно Observer (получатель) и Observable (источник). Это горячий источник данных, что означает, что значения разделяются между всеми subscribers.

import { Subject } from "rxjs";

// Создание Subject
const mySubject = new Subject();

// Subject может одновременно быть источником и слушателем
const subscription1 = mySubject.subscribe({
  next: (value) => console.log("Подписчик 1:", value),
});

mySubject.next(1);
mySubject.next(2);

// Подписываемся позже
const subscription2 = mySubject.subscribe({
  next: (value) => console.log("Подписчик 2:", value),
});

mySubject.next(3);
mySubject.next(4);

mySubject.complete();

// Вывод:
// Подписчик 1: 1
// Подписчик 1: 2
// Подписчик 2: 3
// Подписчик 1: 3
// Подписчик 2: 4
// Подписчик 1: 4

Заметь, что Подписчик 2 получает только значения, которые были эмитированы после его подписки.

Типы Subjects

BehaviorSubject - хранит последнее значение и отправляет его новым subscribers:

import { BehaviorSubject } from "rxjs";

const behaviorSubject = new BehaviorSubject(0);

behaviorSubject.subscribe((value) => console.log("Подписчик 1:", value));
// Вывод: Подписчик 1: 0 (начальное значение)

behaviorSubject.next(1);

behaviorSubject.subscribe((value) => console.log("Подписчик 2:", value));
// Вывод: Подписчик 2: 1 (последнее значение)

behaviorSubject.next(2);
// Вывод:
// Подписчик 1: 2
// Подписчик 2: 2

ReplaySubject - воспроизводит последние N значений для новых subscribers:

import { ReplaySubject } from "rxjs";

const replaySubject = new ReplaySubject(2); // Помнит последние 2 значения

replaySubject.next(1);
replaySubject.next(2);
replaySubject.next(3);

replaySubject.subscribe((value) => console.log("Подписчик:", value));
// Вывод:
// Подписчик: 2
// Подписчик: 3

Сравнительная таблица

ХарактеристикаObservableSubject
Тип потокаХолодныйГорячий
ВыполнениеПри каждой подпискеОдин раз
Совместное использованиеНетДа
Может быть ObserverНетДа
Может быть ObservableДаДа
MulticastНетДа

Практический пример: Event Emitter

Рассмотрим реальный сценарий - обработка кликов:

import { Subject, fromEvent } from "rxjs";

// Observable - создается свежий поток для каждого subscriber
const clickObservable = fromEvent(document, "click");

// Каждый subscriber слушает клики независимо
clickObservable.subscribe(() => console.log("Слушатель 1: клик"));
clickObservable.subscribe(() => console.log("Слушатель 2: клик"));

// Subject - единая точка распределения событий
const clickSubject = new Subject();

clickSubject.subscribe(() => console.log("Слушатель 1: клик"));
clickSubject.subscribe(() => console.log("Слушатель 2: клик"));

// Отправка события
document.addEventListener("click", () => clickSubject.next());

Практический пример: Управление состоянием

import { BehaviorSubject } from "rxjs";

class UserService {
  private userSubject = new BehaviorSubject(null);
  
  // Публичный Observable для подписки
  user$ = this.userSubject.asObservable();
  
  // Способ обновить данные
  setUser(user) {
    this.userSubject.next(user);
  }
  
  getUser() {
    return this.userSubject.value;
  }
}

const userService = new UserService();

userService.user$.subscribe((user) => {
  console.log("Пользователь обновлен:", user);
});

userService.setUser({ id: 1, name: "Иван" });
// Вывод: Пользователь обновлен: { id: 1, name: "Иван" }

Когда использовать Observable

  1. Для асинхронных операций - fetch запросы, таймеры
  2. Для одноразовых потоков - когда каждому subscriber нужна независимая последовательность
  3. Для функциональных операций - когда нужно применять операторы (map, filter)
  4. Для чистоты - нет побочных эффектов

Когда использовать Subject

  1. Для event emitter - кнопки, формы, события пользователя
  2. Для управления состоянием - особенно BehaviorSubject
  3. Для многоадресной отправки - когда несколько компонентов должны получить одно событие
  4. Для двусторонней коммуникации - когда нужна обратная связь

Заключение

Observable - это холодный, функциональный инструмент для работы с потоками данных. Subject - это горячий, императивный инструмент для распределения событий и состояния. Выбирай Observable для обработки данных, Subject для коммуникации между компонентами.

В чем разница между Observable и Subject? | PrepBro