We all want our applications to be responsible, reliable and testable. But event-driven paradigm sometimes could lead us to obscured or, even worse, messy code. Let’s look into the world, where generated data, background tasks and events are stuck together as asynchronous data streams to achieve a better result.
2. WHY REACTIVE?
● Have a curious interface (-= and +=)
● Are difficult to compose
● Don't offer the ability to be easily queried over time
● Provide almost no help for concurrency or multithreaded applications
● No blocking while waiting for a result
● The result is pushed to you when it is ready
● Developers need tools to react to pushed data
EVENTS
● Have nothing to do with events
● Handling exceptions, cancellation and synchronization is difficult
● Much better that events, but still difficult to compose
TASKS
REACTIVE IS THE NEW BLACK
REACTIVE PROGRAMMING IS PROGRAMMING WITH ASYNCHRONOUS DATA STREAMS
3. RX: HELPFUL RESOURCES
GitHub
https://github.com/Reactive-Extensions
NuGet
System.Reactive (main library)
> Install-Package System.Reactive
MSDN
https://msdn.microsoft.com/library/hh242985.aspx
“Intro to Rx” by Lee Campbell
http://introtorx.com
Online / Kindle / EPUBStack Overflow
system.reactive tag
http://stackoverflow.com/questions/tagged/system.reactive
4. RX: IMPLEMENTATIONS
Rx.NET - Reactive Extensions for .NET
RxJS - Reactive Extensions for JavaScript
RxJS-ExtJS - Ext JS Bindings for RxJS
rx.angular.js - AngularJS Bindings for RxJS
RxJS-DOM - HTML DOM Bindings for RxJS
RxCpp - Reactive Extensions for C++
Rx.ObjC - Reactive Extensions for Objective C
RxPy - Reactive Extensions for Python
5. WHAT IS RX?
Rx is a library for composing asynchronous and event-based programs using
observable sequences and LINQ-style query operators.
With Rx you:
- represent asynchronous data streams with Observables
- query asynchronous data streams using LINQ operators
- control the concurrency in the asynchronous data streams using Schedulers.
Rx = Observables + LINQ + Schedulers
12. OBSERVABLE: FACTORIES#4
Bob → Bill → Alice → OnCompleted
var names = Observable.Create<string>(
observer =>
{
observer.OnNext("Bob");
observer.OnNext("Bill");
observer.OnNext("Alice");
observer.OnCompleted();
return Disposable.Empty;
});
Not asynchronous
Not cancellable
var observable = Observable.Create<int>(observer => {
var cd = new CancellationDisposable();
var pause = TimeSpan.FromSeconds(3);
int counter = 0;
Action action = () => {
if (!cd.Token.IsCancellationRequested) {
observer.OnNext(++counter);
if (counter == 5)
observer.OnCompleted();
else
scheduler.Schedule(pause, action);
}
};
scheduler.Schedule(action);
return cd;
});
1 → 2 → 3 → 4 → 5 → OnCompleted
13. OBSERVABLE: CANCELLATION
Subscribe() returns an IDisposable. Keep it.
public void Initialize()
{
this._updateUriDisposable = Observable
.FromEventPattern<EventHandler<UriChangedEventArgs>, UriChangedEventArgs>(
h => this.Options.UriChanged += h,
h => this.Options.UriChanged -= h)
.SelectMany(args => this.RestRequestService.Get(args.EventArgs.Uri, Scheduler.ThreadPool))
.ObserveOn(this.Dispatcher)
.Subscribe(
response => this.WebView.Update(response),
ex => this.HandleError(ex));
}
public void Close() { this._updateUriDisposable.Dispose(); }
Call Dispose on it to stop the Observable.
14. OBSERVABLE: CLEANUP
RX IS TIDY WHEN
Observable has finished with
OnCompleted or OnError
Observable was manually
stopped by Disposable
var changedDisposable = Observable.FromEventPattern(model, nameof(model.Changed))
.Finally(() => Console.WriteLine("Disposed!"))
.Subscribe();
//...
changedDisposable.Dispose();
Use Finally()
when you want
to track disposal
of the data stream
15. LINQ: OVERVIEW
- projection
- filtering
- aggregation
- composing
- time-based operations
You could think:
RX is LINQ to events
16. LINQ: FILTERING
Where
Take / TakeWhile
Skip / SkipWhile
FirstAsync
LastAsync
Observable
.FromEventPattern(
h => textBox.KeyPress += h,
h => textBox.KeyPress -= h)
.Where(_ => _.EventArgs.KeyCode == Keys.Enter)
.Skip(10)
.Take(3)
.FirstAsync()
.Subscribe(_ => { });
EventPattern → OnCompleted