Muhammad AbdulMoiz
Software Developer at Sastaticket.pk
In computing reactive programming is an asynchronous programming paradigm concerned with data streams and propogation of change.
Reactive programming
RxJS
Provide a set of reactive extensions on which we can perform reactive programming
After looking at this diagram, many software developers will say, “We already know this. This is a pub-sub messaging with the implementation of the Observer pattern.” To some extent, this is correct, but there’s more to it:
1. Rx is meant for the asynchronous non-blocking data processing.
2. Rx offers a simple API with dedicated channels for sending data, errors, and the end-of-stream signal.
3. Any Rx library has about a hundred operators that can be applied to the data stream en route. Operators are easily composable.
4. Some of the Rx implementations (e.g. RxJava2) support the backpressure well. This is a scenario when a producer emits data faster than a consumer can handle.
5. You don’t need special messaging servers to use a Rx library. Everything you need is a part of your app.
So how an Observable sends the data to the Observer? An Observer can implement three methods (their names may slightly vary depending on the language you use):
* next() – here’s a new value from the stream
* error() – here’s an error happened in the stream
* complete() – the stream’s over
**Observer has following options**
* subscribe - subscribe to the new values
* unsubscribe -unsubscribe from subscriptions
Observer Design Pattern
Observable maintains a list of its observers and not anyone can listen to the changes in Observables. Observers explicity ask Observables to add them to the observer list.
Two main components
- Observables
- Observers
// Installing RxJS
npm install rxjs-es
// Import and use
import Rx from 'rxjs/Rx';
Rx.Observable.of(1,2,3)
// Import only which you need
// Size sensitive bundling
import { Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
Observable.of(1,2,3).map(x => x + '!!!'); // etc
RXJS installation
code block
// Implementation with RxJS
const observable = Rx.Observable.from([1,2,3]); // Observable
const observer = observable.subscribe((val) => console.log('Value: ', val)); // Observer
// Output would be
// Value: 1
// Value: 2
// Value: 3
code block
// Implementation with RxJS
var observable = Rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
setTimeout(() => {
observer.next(3);
observer.complete();
}, 3000);
observer.complete();
});
observable.subscribe(
value => console.log(value), // Received values
err => {}, // Error thrown
() => console.log('this is the end') // Marking completion
);
// Logs
// 1
// 2
// 3
// "this is the end"
code block
// Implementation with RxJS
// Emitting an error message
const observable = Rx.Observable.create((observer) => {
observer.error('something went really wrong...');
});
observable.subscribe(
value => console.log(value), // will never be called
err => console.log(err),
() => console.log('complete') // will never be called
);
// Logs
// "something went really wrong..."
code block
// Implementation with RxJS
// Unsubscribe method
const observable = Rx.Observable.create(observer => {
const id = setTimeout(() => observer.next('...'), 5000); // emit value after 5s
return () => { clearTimeout(id); console.log('cleared!'); };
});
const subscription = observable.subscribe(value => console.log(value));
setTimeout(() => subscription.unsubscribe(), 3000); // cancel subscription after 3s
// Logs:
// "cleared!" after 3s
// Never logs "..."
Push over pull natrue
Pull - Observer ask observable for value
Push - Observable pushes the value to all of its observables
Real world usage
Listening key strokes
Mouse pointer position detections
Any real time scenario
Observables vs Promises
PROMISES | OBSERVABLES |
---|---|
- Emits a single value - Not lazy , i.e executes when read - Cannot be cancelled |
- Emits multiple values - Lazy i.e not executes until subscribed - Can be cancelled by unsubscribing |
Operators
Operators are functions that can transform the stream data between the moments when the Observable sent them and the function subscribe() received them. In other words, we can transform the data en route. Rx libraries have lots of operators.
Handling Back pressure with RxJS
var source = getStockData()
.pausableBuffered();
source.subscribeOnNext(function (stock) {
console.log('Stock data: %o', stock);
});
source.pause();
// Resume after five seconds
setTimeout(function () {
// Drains the buffer and subscribeOnNext is called with the data
source.resume();
}, 5000);
Handling Back pressure with RxJS
var source = getStockData()
.controlled();
source.subscribeOnNext(function (stock) {
console.log('Stock data: %o', stock);
});
source.request(2);
// Keep getting more after 5 seconds
setInterval(function () {
source.request(2);
}, 5000);
Marble Diagrams
A word of caution. Rx libraries allow you to write less code, but the code readability suffer. The person who reads the code needs to know Rx as well.
By Muhammad AbdulMoiz