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