Ответ 1
Определение
Мое любимое определение:
Сбой - временная несогласованность в наблюдаемом состоянии.
Определение Scala.Rx:
В контексте FRP сбой - временная несогласованность графика данных. Из-за того, что обновления не происходят мгновенно, но вместо этого требуется время для вычисления, значения в системе FRP могут временно не синхронизироваться в процессе обновления. Кроме того, в зависимости от характера FRP-системы возможно, что узлы будут обновляться более одного раза при распространении.
Пример
Рассмотрим целочисленные переменные a
, b
. Определите sum
и prod
такие, что
sum := a + b
, prod := a * b
.
Перепишите этот пример в JavaFX:
IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
NumberBinding sum = a.add(b);
NumberBinding prod = a.multiply(b);
Теперь напишите небольшую проверку последовательности:
InvalidationListener consistencyCheck = obs -> {
assert sum.intValue() == a.get() + b.get();
assert prod.intValue() == a.get() * b.get();
};
sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);
a.set(1);
b.set(2);
Этот код выходит из строя с ошибкой утверждения в последней строке, потому что:
-
b
обновляется (до 2)-
sum
обновляется (до 3)- `constencyCheck` запускается` a == 1`, `b == 2`, но` prod == 0`, потому что `prod` еще не обновлен
-
Это глюк; prod
временно не соответствует a
и b
.
Устранение сглаживания с использованием ReactFX
Прежде всего, обратите внимание, что ReactFX не "сбой" из коробки, но он дает вам инструменты для устранения сбоев. Если вы не предпримете каких-либо сознательных усилий для их использования, ReactFX не будет более сбойным, чем RX (например, rxJava).
Методы устранения сбоев в ReactFX основаны на том, что распространение событий является синхронным. С другой стороны, распространение событий в RX всегда асинхронно, поэтому эти методы не могут быть реализованы в RX-системе.
В приведенном выше примере мы хотим отложить уведомления о прослушивании до тех пор, пока не будут обновлены как теги sum
, так и prod
. Вот как это сделать с помощью ReactFX:
import org.reactfx.Guardian;
import org.reactfx.inhibeans.binding.Binding;
IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
Binding<Number> sum = Binding.wrap(a.add(b)); // Binding imported from ReactFX
Binding<Number> prod = Binding.wrap(a.multiply(b)); // Binding imported from ReactFX
InvalidationListener consistencyCheck = obs -> {
assert sum.getValue().intValue() == a.get() + b.get();
assert prod.getValue().intValue() == a.get() * b.get();
};
sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);
// defer sum and prod listeners until the end of the block
Guardian.combine(sum, prod).guardWhile(() -> {
a.set(1);
b.set(2);
});