Reactive Programming
- What is Reactive Programming?
- Introduction to ReactiveX
- ReactiveX Case study
- ReactiveX Pro Tips
Schedules
What is Reactive Programming?
Is just observe & react to changes ?
// java
class Activity {
int clickCount = 0;
function onCreate(){
button.setOnClickListener(() -> {
clickCount += 1;
doSomething();
});
}
function doSomething(){ /* implementation */ }
}
No!!!!
What is Reactive Programming?
Programming with Event-Driven model?
// java
class Activity {
int clickCount = 0;
function onCreate(){
button.setOnClickListener(() -> {
EventHub.publish(AddClickCountEvent());
EventHub.publish(DoSomethingEvent());
});
}
function onReceive(AddClickCountEvent event) {
clickCount += 1;
}
function onReceive(DoSomethingEvent event) { /* implementation */ }
}
No!!!!
What is Reactive Programming?
Programming with Asynchronous data stream
// java
class Activity {
Observable<Void> clickStream;
Observable<Integer> clickCountStream;
function onCreate(){
// create a click data stream
clickStream = Observable.create(observer -> {
button.setOnClickListener(() -> {
observer.onNext()
});
});
// transform every click to a integer 1
// accumulate on every integer `x`
clickCountStream = clickStream
.map(() -> 1)
.scan((accu, x) -> accu + x);
}
}
What is Reactive Programming?
Programming with Asynchronous data stream
clickCountStream = clickStream
.map(() -> 1)
.scan((accu, x) -> accu + x);
Click
ClickCount
1
1
1
1
2
3
map( x -> 1 )
scan(accu,x -> accu + x )
What is Reactive Programming?
Programming with Asynchronous data stream
- Data Flow
- Transformation
- Composition
- Scheduler usage
OOP, FP has its own focus. How about RP ?
How can we getting start with RP?
Introduction to ReactiveX
ReactiveX is...
- a combination of the best ideas from Observer pattern, iterator pattern and functional programming
- an idea and a breakthrough in programming
- everywhere. 16+ Supported language. Variety usage on Frontend and Backend
- a high level abstraction of modeling data
Introduction to ReactiveX
Introduction to ReactiveX
ReactiveX 101
- Observable
- Subject
- Scheduler
- Subscription
Reactive Case Study
- Hardest part on adopting ReactiveX
- Simple Combination of Stream
- Throttling user's input
Reactive Case Study
Hardest part on adopting ReactiveX
- Temptation on using old imperative and stateful style
- Thinking in Reactive way to solve problems
- Lack of Functional Programming experience
Reactive Case Study
Simple Combination of Stream
// Swift
let a = BehaviourSubject<Int>(value: 1)
let b = BehaviourSubject<Int>(value: 2)
let c = Observable.combineLatest(a,b) { a,b -> a + b }
XCTAssert(c.last() == 3)
a.onNext(10)
XCTAssert(c.last() == 12)
b.onNext(50)
XCTAssert(c.last() == 60)
a.onNext(1)
a.onNext(2)
a.onNext(3)
XCTAssert(c.last() == 53)
Reactive Case Study
Throttling user's input
// version 1
func fetchGoogleMap(word: String, success:(Result) -> () ){/* Implementation */}
func onTextChanges(word: String) {
fetchGoogleMap(word, success: { result in
self.displayResult(result)
})
}
Problems?
Every single input will trigger the API Call...
But each API Call response time is different,
we can't guarantee the last API response is come from the last input
Reactive Case Study
Throttling user's input
// version 2
private var lastRequest: NSURLSessionTask?
func fetchGoogleMap(word: String, success:(Result) -> ())
-> NSURLSessionTask {/* Implementation */}
func onTextChanges(word: String) {
lastRequest?.cancel()
lastRequest = nil
lastRequest = fetchGoogleMap(word, success: { result in
self.displayResult(result)
})
}
Problems?
Every single user input will trigger the API Call... and Cancel it..
Reactive Case Study
Throttling user's input
// version 3
private var lastScheduledWord: dispatch_cancelable_block_t?
private var lastRequest: NSURLSessionTask?
func fetchGoogleMap(word: String, success:(Result) -> ())
-> NSURLSessionTask {/* Implementation */}
func onTextChanges(word: String) {
cancel_block(lastScheduledWord)
lastRequest?.cancel()
lastRequest = nil
// throttle 0.5 second first
lastScheduledWord = dispatch_after_delay(0.5) {
self.lastRequest = fetchGoogleMap(word, success: { result in
self.displayResult(result)
})
}
}
Let see how ReactiveX solve it
Reactive Case Study
Throttling user's input
// version 1 , RxSwift
func fetchGoogleMap(word: String) -> Observable<Result> {/* Implementation */}
func viewDidLoad(){
input.rx.text
.startWith(nil)
.debounce(0.5, scheduler: MainScheduler.instance)
.flatMap(fetchGoogleMap)
.observeOn(MainScheduler.instance)
.subscribe(onNext:{ result in
self.displayResult(result)
})
}
ReactiveX Pro Tips
1. Everything is a Stream
API Call
User's Input
User's Action
View's Event
View's State
Async Callback
ReactiveX Pro Tips
2. Study Operator hardly
map
flatMap
flatMapLatest
scan
replay
startWith
switchMap
debounce
sample
combineLatest
zip
merge
...
ReactiveX Pro Tips
3. Learning Functional Programming
Practise make perfect
Reactive Programming
By Gap撈Tech
Reactive Programming
- 382