Reactive applications are typically associated with enterprise-facing systems but they are fast becoming more and more prevalent in consumer applications.
The reactive manifesto distinguishes a reactive application as having one or more of the following characteristics;
ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.
The observable pattern is demonstrated when an object, called the subject, maintains a list of its dependents, called observables, and notifies them of any state change.
The Observable object represents a push based collection.
The Observable object represents the object that sends notifications (the provider);
the Observer object represents the class that receives them (the observer).
The Observer object provides support for push-style iteration over an observable sequence
ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.
Data sequences are composable event streams and can take many forms
Reactive Programming is programming with asynchronous data streams
Streams are cheap and ubiquitous, anything can be a stream: variables, user inputs, properties, caches, data structures etc.
Data sequences are composable event streams and can take many forms, such as;
var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');
var subscription = mousedown.subscribe(function (pos) {
console.log(pos);
});
var received = 0;
var numbers = new Subject<int>();
numbers.Subscribe((int x) => received += x);
numbers.OnNext(10);
numbers.OnNext(5);
Assert.AreEqual(15, received);
Other examples could include;
by Marble Diagram
By Marble Diagram
by ASCII
clickStream: ---c----c--c----c------c---->|
vvvvv map(c becomes 1) vvvv
---1----1--1----1------1-->
vvvvvvvvv scan(+) vvvvvvvvv
counterStream: ---1----2--3----4------5-->|
c is an emitted value
X is an error
| is the 'completed' signal
---> is the timeline
Given a user clicks
Then capture the click
And increment a counter
And render the counter
ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.
Key Types
IObserver<in T>
IObservable<T>
Provides a mechanism for receiving push-based notifications.
Key Types :: IObservable
//Defines a provider for push-based notification.
public interface IObservable<out T>
{
//Notifies the provider that an observer is to receive notifications.
IDisposable Subscribe(IObserver<T> observer);
}
Key Types :: IObserver
//Provides a mechanism for receiving push-based notifications.
public interface IObserver<in T>
{
//Provides the observer with new data.
void OnNext(T value);
//Notifies the observer that the provider has experienced an error condition.
void OnError(Exception error);
//Notifies the observer that the provider has finished sending push-based notifications.
void OnCompleted();
}
Key Types :: In Action
public class MyConsoleObserver<T> : IObserver<T>
{
public void OnNext(T value)
{
Console.WriteLine("Received value {0}", value);
}
public void OnError(Exception error)
{
Console.WriteLine("Sequence faulted with {0}", error);
}
public void OnCompleted()
{
Console.WriteLine("Sequence terminated");
}
}
Key Types :: In Action
public class MySequenceOfNumbers : IObservable<int>
{
public IDisposable Subscribe(IObserver<int> observer)
{
observer.OnNext(1);
observer.OnNext(2);
observer.OnNext(3);
observer.OnCompleted();
return Disposable.Empty;
}
}
Key Types :: In Action
var numbers = new MySequenceOfNumbers();
var observer = new MyConsoleObserver<int>();
numbers.Subscribe(observer);
Received value 1
Received value 2
Received value 3
Sequence terminated
Output
Nothing Listens until you subscribe.
var sum = 0;
var numbers = Range.Create(1, 10).ToObservable();
var observable = numbers.Do(n => sum += n);
Assert.AreEqual(0, sum);
observable.Subscribe();
Assert.AreEqual(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, sum);
Combine multiple Observables into one
var easy = new StringBuilder();
var you = new object[] {1, 2, 3}.ToObservable();
var me = new object[] {"A", "B", "C"}.ToObservable();
you.Merge(me).Subscribe(a => easy.Append(a + " "));
Assert.AreEqual(easy.ToString(), "1 A 2 B 3 C ");
you stream: ---1-------2-------3----->|
me stream: -------A-------B------C-->|
vvvvvvvvvv merge vvvvvvvvv
easy: 1 A 2 B 3 C
Rx offers a natural paradigm for dealing with sequences of events.
A sequence can contain zero or more events.
Rx proves to be most valuable when composing sequences of events.
Multiple Subscriptions
var numbers = new Subject<int>();
double sum = 0;
double average = 0;
numbers.Sum().Subscribe(n => sum = n);
numbers.OnNext(1, 1, 1, 1, 1);
numbers.Average().Subscribe(n => average = n);
numbers.OnNext(2, 2, 2, 2, 2);
numbers.OnCompleted();
Assert.AreEqual(15, sum);
Assert.AreEqual(average, 2);
Demo
Quiz
var called = "";
var sub = new Subject<double>();
Func<int, double> halve = x =>
{
called += "A";
return x*0.5;
};
double? result = 0;
sub.Subscribe(n =>
{
called += "C";
result = n;
});
halve.BeginInvoke(101, iar =>
{
called += "B";
sub.OnNext(halve.EndInvoke(iar));
sub.OnCompleted();
}, null);
ThreadUtils.WaitUntil(() => result != 0);
Assert.AreEqual(???, result);
Assert.AreEqual("Whats this answer", called);
Typical examples of Reactive applications are Financial Trading applications.