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

Что такое Cold Observable?

1.3 Junior🔥 11 комментариев
#Многопоточность и асинхронность

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Что такое Cold Observable?

В контексте RxSwift или других реактивных фреймворков (ReactiveX), Cold Observable — это особый тип Observable последовательности, которая начинает производить элементы (emit items) только после того, как на нее подписались (subscribe). Производство данных происходит для каждого подписчика независимо, и последовательность не "разделяется" между подписчиками. Это похоже на чтение данных из источника, который предоставляет данные отдельно для каждого запроса, например, из файла, сети или локальной базы данных.

Ключевые характеристики Cold Observable

  • Ленивое выполнение (Lazy Execution): Поток данных не начинает генерироваться до момента подписки. Сам Observable часто описывает, как получить данные, но не делает этого заранее.
  • Индивидуальное производство для каждого подписчика: Если два разных подписчика (Observer) подписываются на один и тот же Cold Observable, каждый из них получит полную, независимую последовательность данных. Observable для каждого подписчика выполнит свою внутреннюю логику (например, совершит два отдельных сетевых запроса).
  • Источник данных закрыт или статичен: Данные часто берутся из источника, который можно "открыть" многократно без изменения состояния последовательности (например, чтение файла, запрос к базе данных, вычисление значения).

Пример Cold Observable в RxSwift

Рассмотрим простейший пример: создание Observable из массива. Это классический Cold Observable.

import RxSwift

let coldObservable = Observable.from([1, 2, 3, 4, 5])

// Первый подписчик
coldObservable
    .subscribe(onNext: { element in
        print("Subscriber 1: \(element)")
    })

// Второй подписчик (подпишемся позже)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    coldObservable
        .subscribe(onNext: { element in
            print("Subscriber 2: \(element)")
        })
}

В выводе мы увидим:

Subscriber 1: 1
Subscriber 1: 2
Subscriber 1: 3
Subscriber 1: 4
Subscriber 1: 5
Subscriber 2: 1
Subscriber 2: 2
Subscriber Small 2: 3
Subscriber 2: 4
Subscriber 2: 5

Оба подписчика получили полную и одинаковую последовательность чисел. Observable from не "запомнил" состояние и начал генерацию с первого элемента для каждого нового подписчика.

Сравнение с Hot Observable

Противоположностью является Hot Observable, который:

  • Производит данные независимо от наличия подписчиков (например, поток событий UI, таймер, общие данные от сервера).
  • Разделяет один поток данных между всеми текущими подписчиками. Если подписчик присоединился позже, он может пропустить ранее emitted элементы.
  • Часто представляет собой "живой", непрерывный или событийный источник.

Типичные источники для Cold Observable

  • Сетевые запросы: Каждая подписка может trigger новый HTTP запрос.
  • Чтение файлов или данных из БД: Каждый подписчик читает данные с начала.
  • Вычисления или преобразования: Например, Observable.just(42) или результат тяжелой операции.
  • Последовательности, созданные операторами deferred, create, from.

Практический пример с сетевым запросом

func fetchUserData(userId: Int) -> Observable<User> {
    // Это Cold Observable: каждый subscribe вызовет новый URLSession запрос.
    return Observable.create { observer in
        let task = URLSession.shared.dataTask(with: URL(string: "https://api.example.com/user/\(userId)")!) { data, response, error in
            if let error = error {
                observer.onError(error)
            } else if let data = data {
                // Парсинг и отправка данных
                let user = try JSONDecoder().decode(User.self, from: data)
                observer.onNext(user)
                observer.onCompleted()
            }
        }
        task.resume()
        return Disposables.create {
            task.cancel()
        }
    }
}

// Два разных подписчика сделают два независимых запроса к серверу.
let userObservable = fetchUserData(userId: 1)
userObservable.subscribe(onNext: { print("Subscriber A got: \($0)") })
userObservable.subscribe(onNext: { print("Subscriber B got: \($0)") })

Преобразование Cold в Hot

Cold Observable иногда преобразуют в Hot с помощью операторов sharing, чтобы избежать повторения дорогостоящих операций для каждого подписчика:

  • share() или share(replay:scope:) в RxSwift
  • publish() + connect() или multicast

Это позволяет "разделить" результат одной генерации между несколькими подписчиками.

Итог

Cold Observable — это фундаментальная концепция в реактивных программах, представляющая индивидуальные, ленивые потоки данных. Понимание различий между Cold и Hot важно для корректного управления ресурсами (например, чтобы не делать лишних сетевых запросов), поведения приложения и эффективности кода. При работе с RxSwift всегда анализируйте, является ваш Observable Cold или Hot, чтобы правильно применять операторы и стратегии подписки.

Что такое Cold Observable? | PrepBro