Погружаясь в реактивное программирование, я часто сталкиваюсь с ситуациями, когда два потока зависят друг от друга. Что такое идиоматический способ решения этих дел?Циклические зависимости между потоками в реактивном программировании
Минимальный пример: есть кнопки A и B, оба отображают значение. Нажатие на A должно увеличивать значение A на B. Нажатие на B должно установить значение B в A.
Первое решение, которое я мог бы придумать (например, в F #, но ответы на любом языке приветствуются):
let solution1 buttonA buttonB =
let mutable lastA = 0
let mutable lastB = 1
let a = new Subject<_>()
let b = new Subject<_>()
(OnClick buttonA).Subscribe(fun _ -> lastA <- lastA + lastB; a.OnNext lastA)
(OnClick buttonB).Subscribe(fun _ -> lastB <- lastA; b.OnNext lastB)
a.Subscribe(SetText buttonA)
b.Subscribe(SetText buttonA)
a.OnNext 0
b.OnNext 1
Это решение использует изменчивое состояние и предметы, оно не очень читаемо и не выглядит идиоматическим.
Второе решение, которое я попытался включает в себя создание метода, который связывает два зависимых потоков вместе:
let dependency (aGivenB: IObservable<_> -> IObservable<_>) (bGivenA: IObservable<_> -> IObservable<_>) =
let bProxy = new ReplaySubject<_>()
let a = aGivenB bProxy
let b = bGivenA a
b.Subscribe(bProxy.OnNext)
a, b
let solution2 buttonA buttonB =
let aGivenB b =
Observable.WithLatestFrom(OnClick buttonA, b, fun click bValue -> bValue)
.Scan(fun acc x -> acc + x)
.StartWith(0)
let bGivenA a =
Observable.Sample(a, OnClick buttonB)
.StartWith(1)
let a, b = dependency aGivenB bGivenA
a.Subscribe(SetText buttonA)
b.Subscribe(SetText buttonB)
Это кажется немного лучше, но так как не существует способа, как dependency
в реакционно-библиотеке, я считаю, что существуют более идиоматическое решение. Также легко ввести бесконечную рекурсию, используя второй подход.
Каков рекомендуемый способ решения проблем, связанных с циклической зависимостью между потоками, например, в приведенном выше примере, в реактивном программировании?
Может быть, проблема "изменяемые данные". Я думал, что реактивное программирование лучше всего работает, когда выполняется в функциональном стиле. – duffymo
Функциональный подход без «изменчивых данных» был бы предпочтительнее, я просто еще не знаю, как это сделать в этом примере. – Steve