В чем разница между Cold Publisher и Hot Publisher в реактивном программировании?

Ответ

Cold Publisher начинает генерировать события (эмитировать значения) только при появлении подписчика (subscriber). Каждый новый подписчик запускает независимую последовательность событий. Это ленивая (lazy) и индивидуальная стратегия.

Hot Publisher генерирует события независимо от наличия подписчиков и делит один поток событий между всеми текущими подписчиками. Подписчик, подключившийся позже, может пропустить ранее отправленные события.

Ключевые отличия:

  • Инициация: Cold — по подписке, Hot — независимо.
  • Данные: Cold — индивидуальный поток для каждого подписчика, Hot — общий (shared) поток.
  • Примеры в Combine: URLSession.dataTaskPublisher, Just, Future (обычно cold). PassthroughSubject, CurrentValueSubject, share() оператор (hot).

Пример Cold Publisher:

let coldPublisher = [1, 2, 3].publisher // Данные генерируются для каждого подписчика
let subscription1 = coldPublisher.sink { print("Sub1: ($0)") } // Печатает 1,2,3
let subscription2 = coldPublisher.sink { print("Sub2: ($0)") } // Снова печатает 1,2,3

Пример Hot Publisher:

let hotSubject = PassthroughSubject<Int, Never>()
// Отправляем до подписки — событие теряется
hotSubject.send(0)
// Подписываемся
let subscription1 = hotSubject.sink { print("Sub1: ($0)") }
hotSubject.send(1) // Sub1: 1
let subscription2 = hotSubject.sink { print("Sub2: ($0)") }
hotSubject.send(2) // Sub1: 2, Sub2: 2

Ответ 18+ 🔞

Так, слушай, про эти ваши паблишеры, холодные и горячие, я тебе сейчас так объясню, что ты, блядь, на всю жизнь запомнишь. Это ж элементарно, ёпта!

Представь себе, что Cold Publisher — это как я, сука, когда готовлю тебе индивидуальный завтрак. Пока ты не пришёл и не сказал: «Слушай, я есть хочу!» — я на кухне сижу и в телефоне туплю. Но как только ты подписался, я встаю, блядь, и начинаю жарить яичницу именно для тебя. Второй чувак пришёл — я ему тоже с нуля, блядь, новую яичницу делаю. Каждый получает свою, свежую, полную последовательность яиц. Это ленивая, индивидуальная хуйня. URLSession.dataTaskPublisher — классический пример: каждый раз, когда подписываешься, новый сетевой запрос, новая порция данных.

А теперь Hot Publisher — это как радиостанция, ёбта. Она вещает в эфир, похуй, слушает кто-то или нет. Музыка играет, диктор пиздит. Ты включил приёмник (подписался) — ты ловишь то, что сейчас в эфире. Что было до твоего включения — тебе, блядь, навсегда писец, ты это проёбал. И если мы с тобой на одной волне, мы слышим одно и то же, общий поток. PassthroughSubject — это оно и есть, чистейший горячий источник. Отправил событие до подписки — оно улетело в никуда, как моя молодость, блядь.

Короче, ключевые отличия, чтобы не ебать мозг:

  • Кто начинает? Холодный — только когда подписчик пришёл. Горячий — пиздит сам по себе, как сосед за стенкой.
  • Что за данные? Холодный — каждому своя, уникальная копия потока. Горячий — один на всех, общий шаринг.
  • Примеры в Combine: Холодные — Just, Future, запросы к сети. Горячие — PassthroughSubject, CurrentValueSubject. А ещё есть оператор share() — он холодного паблишера превращает в горячего, чтобы все подписчики делили одну подписку, а не запускали новые.

Вот тебе живой пример Cold Publisher, смотри:

let coldPublisher = [1, 2, 3].publisher // Данные генерируются для каждого подписчика
let subscription1 = coldPublisher.sink { print("Sub1: ($0)") } // Печатает 1,2,3
let subscription2 = coldPublisher.sink { print("Sub2: ($0)") } // Снова печатает 1,2,3

Видишь? Каждый подписчик получает свою, отдельную, полную хуйню от начала до конца. Как два разных человека смотрят один и тот же фильм на своих ноутах.

А теперь пример Hot Publisher, в рот меня чих-пых:

let hotSubject = PassthroughSubject<Int, Never>()
// Отправляем до подписки — событие теряется нахуй в пустоту!
hotSubject.send(0) // Прощай, ноль, тебя никто не увидит.
// Подписываемся
let subscription1 = hotSubject.sink { print("Sub1: ($0)") }
hotSubject.send(1) // Sub1: 1
let subscription2 = hotSubject.sink { print("Sub2: ($0)") }
hotSubject.send(2) // Sub1: 2, Sub2: 2

Вот! Ноль ушёл в нирвану. Первый подписчик поймал единицу. Когда подключился второй, он начал ловить события только с этого момента. А двойку они уже получили оба, потому что поток один на двоих.

Вот и вся, блядь, философия. Не усложняй. Холодный — индивидуальный и ленивый. Горячий — общий и независимый. Запомнил?