Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Реактивное программирование / Живые supply и supply по требованию
Живые supply в действии
Поскольку живой supply вещает тем подключениям, которые слушают в
данный момент, за одним и тем же потоком могут следить сразу несколько
слушателей, и каждый волен присоединиться или уйти когда угодно. Здесь
за потоком событий наблюдают двое: log, который записывает
всё, и alert, который присоединяется позже и уходит
раньше.
my $supplier = Supplier.new;
my $events = $supplier.Supply;
my $log = $events.tap(-> $v { say "log: $v" }); # присоединяется первый слушатель
$supplier.emit('start');
my $alert = $events.tap(-> $v { say "alert: $v" }); # присоединяется второй слушатель
$supplier.emit('warning');
$supplier.emit('all clear');
$log.close; # первый слушатель уходит
$supplier.emit('stop');Программа печатает:
log: start
log: warning
alert: warning
log: all clear
alert: all clear
alert: stopЖизненный цикл двух подключений выстраивается так: 🟢 отмечает присоединение подключения, 🔴 — его уход, а ✅ — каждое значение, которое подключение действительно получило:
| Шаг | log |
alert |
|---|---|---|
$events.tap → log |
🟢 присоединяется | |
emit 'start' |
✅ start | |
$events.tap → alert |
🟢 присоединяется | |
emit 'warning' |
✅ warning | ✅ warning |
emit 'all clear' |
✅ all clear | ✅ all clear |
$log.close |
🔴 уходит | |
emit 'stop' |
✅ stop |
Пустая клетка означает, что в момент выдачи значения это подключение не слушало. Проследим за временной линией:
.tapвозвращает объектTap— рукоятку, которую вы сохраняете, чтобы управлять именно этой подпиской.startвыдаётся, когда слушает толькоlog, поэтому его видит толькоlog. Это снова правило живого supply:alertприсоединился послеstart, а живой supply прошлое не проигрывает, так чтоalertэтого значения никогда не увидит.warningиall clearвыдаются, когда подключены оба, поэтому каждое значение доходит до обоих — в том порядке, в каком они подписались: сначалаlog, затемalert.- Вызов
$log.closeотсоединяет от supply. С этого моментаlogне получает ничего, поэтому последнееstopдоходит только доalert.
Отсюда два вывода. Во-первых, один живой supply способен
разветвляться сразу на множество независимых подключений. Во-вторых,
каждое подключение — отдельная подписка со своим временем жизни:
сохраните объект Tap, который возвращает .tap,
и вы сможете прекратить именно этого слушателя методом
.close, не потревожив остальных.
Навигация по курсу
← Живые supply | Два подключения →
💪 Или перейдите сразу к упражнениям этого
раздела.