Reactive Extensions (Rx) is now Open Source
A few years back I did a podcast with Erik Meijer about Reactive Extensions for .NET (Rx). Since then thousands of people have enjoyed using Rx in the projects and a number of open source projects like ReactiveUI (also on the podcast) have popped up around it. Even GitHub for Windows uses Reactive Extensions. In fact, GitHub uses Rx a LOT in their Windows product. My friend Paul at GitHub says they liked the model so much they made a Mac version!
“GitHub for Windows uses the Reactive Extensions for almost everything it does, including network requests, UI events, managing child processes (git.exe). Using Rx and ReactiveUI, we've written a fast, nearly 100% asynchronous, responsive application, while still having 100% deterministic, reliable unit tests. The desktop developers at GitHub loved Rx so much, that the Mac team created their own version of Rx and ReactiveUI, called ReactiveCocoa, and are now using it on the Mac to obtain similar benefits.” – Paul Betts, GitHub
Today, Microsoft Open Technologies announced the open sourcing of Reactive Extensions! You can get the code with git up on Codeplex at https://rx.codeplex.com. You can’t stop the open source train! Congrats to the team!
There’s a LOT included, so be stoked. It’s not just Rx.NET, but also the C++ library as well as RxJS for JavaScript! Now everyone gets to play with IObservable<T> and IObserver<T>.
- Reactive Extensions:
- Rx.NET: The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators.
- RxJS: The Reactive Extensions for JavaScript (RxJS) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators in JavaScript which can target both the browser and Node.js.
- Rx++: The Reactive Extensions for Native (RxC) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators in both C and C++.
- Interactive Extensions
- Ix: The Interactive Extensions (Ix) is a .NET library which extends LINQ to Objects to provide many of the operators available in Rx but targeted for IEnumerable<T>.
- IxJS: An implementation of LINQ to Objects and the Interactive Extensions (Ix) in JavaScript.
- Ix++: An implantation of LINQ for Native Developers in C++
A great way to learn about why Rx is useful is to check out the Rx Koan’s project or to read the IntroToRx online e-book.
Why do I think Rx matters? It’s a way to do asynchronous operations on event streams. Rather than hooking up click events and managing state with event handlers all over, you effectively “query” an infinite stream of events with LINQ. You can declaratively sequence events…no flags, no state machine.
For example, here’s a dragging event created (composed) via Mouse button and Mouse move events:
IObservable<Event<MouseEventArgs>> draggingEvent =
from mouseLeftDownEvent in control.GetMouseLeftDown()
from mouseMoveEvent in control.GetMouseMove().Until(control.GetMouseLeftUp())
select mouseMoveEvent;
Even better, Rx makes it easier (or possible!) to create event-based tests that are asynchronous, like this example from Jafar Husain:
Rating rating = new Rating();
IObservable<Unit> test = // Unit is an object that represents null.
ObservableExtensions
.DoAsync(() => TestPanel.Children.Add(rating))
.WaitFor(TestPanel.GetLayoutUpdated()) // Extension method GetLayoutUpdated converts the event to observable
.DoAsync(() => rating.Value = 1.0) // Calls the Ignite EnqueueCallback method
.WaitFor( // waits for an observable to raise before going on
// listen to all the actual value change events and filters them until ActualValue reaches Value
rating
.GetActualValueChanged() // extension method that converts ActualValueChanged event to IObservable
.SkipWhile(actualValueChangedEvent => actualValueChangedEvent.EventArgs.NewValue != rating.Value))
// check to make sure the actual value of the rating item is set appropriately now that the animation has completed
.Assert(() => rating.GetRatingItems().Last().ActualValue == 1.0) // crawls the expression tree and makes a call to the appropriate Assert method
Test.Subscribe(() => TestPanel.Children.Remove(rating)); //run the test and clean up at the end.
There’s amazing Time-related operators that let you simulate events over time. Note the Buffer and Subscribe calls.
var myInbox = EndlessBarrageOfEmail().ToObservable();
// Instead of making you wait 5 minutes, we will just check every three seconds instead. :)
var getMailEveryThreeSeconds = myInbox.Buffer(TimeSpan.FromSeconds(3)); // Was .BufferWithTime(...
getMailEveryThreeSeconds.Subscribe(emails =>
{
Console.WriteLine("You've got {0} new messages! Here they are!", emails.Count());
foreach (var email in emails)
{
Console.WriteLine("> {0}", email);
}
Console.WriteLine();
});
You can use await and async, like in this example returning the number 42 after 5 seconds:
static async void button_Click()I’m just showing you the parts that tickle me, but one could easily teach a 10 week university course on Rx, and I’m still a beginner myself!
{
int x = await Observable.Return(42).Delay(TimeSpan.FromSeconds(5));
// x with value 42 is returned after 5 seconds
label.Text = x.ToString();
}
Here’s some more resources to check out about Rx. Congrats to the team for their contribution to Open Source!
- MSDN on Rx
- DevCamp 2010 Keynote - Rx: Curing your asynchronous programming blues
- Kim Hamilton and Wes Dyer: Inside .NET Rx and IObservable/IObserver in the BCL (VS 2010)
- Going Deep: Rx on .NET 4.5 and WinRT
- E2E: Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx)
- E2E: Erik Meijer and Wes Dyer - Reactive Framework (Rx) Under the Hood 1 of 2
- E2E: Erik Meijer and Wes Dyer - Reactive Framework (Rx) Under the Hood 2 of 2
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Rx replaces neither SignalR nor Knockout.js. In fact, SignalR and Rx work great together. As an example, you could use Rx (.NET) to work with a series of server side events and then send transformed/filtered/etc events to the client using SignalR. You could also do thing the other way round, and let SignalR send a stream of events to a client application (say a browser app) and let Rx (the JavaScript flavor) filter/transform/etc those events directly on the client before displaying them to the user.
To echo @Paul's comment, we don't aim to replace Knockout.js at all where ko is really good at observable bindings for objects, RxJS is a more general purpose library which works across runtimes for more complex queries such as mapping, filtering, aggregation, etc.
You might want to think of more scenarios such as a dictionary suggest where you read input from the keyboard and query a service, while keeping in mind throttling the user's input so we don't flood the service, as well as handling things such as out of order results:
Autocomplete scenario
Another way to think about it is with rich events where you can combine together distinct events such as mouse down and mouse move until mouse up, and then you have a single object that you can pass around which now represents a mouse drag and drop event:
Drag and Drop Example
We have more examples here that you may be interested in looking at:
Examples
Matt
Because RX is a weak reference, I thought it was a great way from worrying about de-referencing event handlers.
The next time I thought about RX, was with INotifyPropertyChanged events, and how binding works declaritively.
In both of these cases, I wonder why MS hasn't used RX deeper in the architecture - and allow subscriptions from the application layer.
Either way I would love to hear more shows about RX and how to categorize it's uses - perhaps with Paul Betts and understanding his learning curve with RX.
Comments are closed.