Я экспериментирую с Reactive Extensions на разных платформах, и одна вещь, которая меня немного раздражает, — это глюки.
Хотя для кода пользовательского интерфейса эти сбои могут не вызывать таких проблем, и обычно можно найти оператора, который их обходит, мне все еще сложнее отлаживать код при наличии сбоев: промежуточные результаты не важны для отладки, но мой разум не знает, когда результат промежуточный или «окончательный».
Поработав немного с чистым функциональным FRP в Haskell и синхронными системами потока данных, он также «чувствует» себя неправильно, но это, конечно, субъективно.
Но при подключении RX к исполнительным механизмам без пользовательского интерфейса (например, двигателям или переключателям), я думаю, сбои становятся более проблематичными. Как убедиться, что на внешние приводы отправляется только правильное значение?
Может быть, это может быть решено каким-то «диспетчером», который знает, когда какой-то «внешний датчик» запустил инициирующее событие, так что все внутренние события обрабатываются перед отправкой окончательных результатов на исполнительные механизмы. Примерно так, как описано в бумаге по flapjax.
Вопросы, на которые я надеюсь получить ответы:
- Есть ли что-то в RX, что делает невозможным исправление сбоев для синхронных уведомлений?
- Если нет, существует ли библиотека (желательно производственного качества) или подход для RX, который исправляет синхронные сбои? Особенно для однопоточного Javascript это может иметь смысл?
- Если общего решения не существует, как можно использовать RX для управления внешними датчиками/исполнительными механизмами без сбоев в исполнительных механизмах?
Позвольте мне привести пример
Предположим, я хочу напечатать последовательность кортежей (a,b)
, где контракт
a=n b=10 * floor(n/10)
n - поток натуральных чисел = 0,1,2....
Поэтому я ожидаю следующую последовательность
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=9, b=0)
(a=10, b=10)
(a=11, b=10)
...
В RX, чтобы сделать вещи более интересными, я буду использовать фильтр для вычисления потока b.
var n = Observable
.Interval(TimeSpan.FromSeconds(1))
.Publish()
.RefCount();
var a = n.Select(t => "a=" + t);
var b = n.Where(t => t % 10 == 0)
.Select(t => "b=" + t);
var ab = a.CombineLatest(b, Tuple.Create);
ab.Subscribe(Console.WriteLine);
Это дает то, что я считал сбоем (временное нарушение инварианта/контракта):
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=10, b=0) <-- glitch?
(a=10, b=10)
(a=11, b=10)
Я понимаю, что это правильное поведение CombineLatest, но я также думал, что это называется сбоем, потому что в реальной чистой системе FRP вы не получаете этих промежуточных результатов, нарушающих инвариант.
Обратите внимание, что в этом примере я бы не смог использовать Zip, а также WithLatestFrom дал бы неверный результат.
Конечно, я мог бы просто упростить этот пример до одного монадического вычисления, никогда не выполняя многоадресную рассылку n вхождений потока (это означало бы, что я не могу фильтровать, а только отображать), но это не главное: IMO в RX вы всегда получаете «глюк». ' всякий раз, когда вы разделяете наблюдаемый поток и снова присоединяетесь к нему:
s
/ \
a b
\ /
t
Например, во FlapJAX таких проблем нет.
Есть ли в этом смысл?
Большое спасибо, Питер
a0-----(b0b1)(c1c4)(d4d9)(e9e16)
по сравнению с желаемым выводомa0-----b1----c4----d9----e16---
, неверен. Фактический результат правильный для этого запроса. Это не сбой - это правильное функционирование этого запроса. Вам действительно нужно создать минимальный воспроизводимый пример, показывающий фактические сбои, чтобы мы могли вам ответить. - person Enigmativity   schedule 18.02.2016CombineLatest
будет работать детерминированным образом. Невозможно иметь дело с мгновенными изменениями значений. Источники должны создавать значения последовательно — один подписчик должен получить значение первым, а другой — вторым, поэтому, если два значения теоретически предназначены для изменения в одно и то же время, они не меняются сделать это в вычислительной реальности. Просто не может быть по-другому. Это особенно верно, поскольку каждый наблюдаемый источник и оператор являются черными ящиками. Нет никакого способа заглянуть внутрь и увидеть, что он теоретически должен делать. - person Enigmativity   schedule 18.02.2016