Workshop:

Advanced RxJS patterns to reactive interfaces

William Grasel

@willgmbr

fb.me/wgrasel

define:

reactive programming 

"Reactive programming is a programming paradigm oriented around data flows and the propagation of change."

What else can be a Stream?

  • User actions
  • Systems events
  • Application state
  • Validation and businesses rules
  • Any data source, async or not!

RxJS

The ReactiveX library for JavaScript.


  [1, 2, 3]
    .map(i => i * 2) // [2, 4, 6]
    .filter(i => i > 5) // [6]
    .concat([10, 20, 30]) // [6, 10, 20, 30]

Operators❤️


  Observable.of(1, 2, 3)
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Observable.of(10, 20, 30)
    )

  Observable.fromEvent(document, 'click')
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Observable.fromEvent(document, 'blur')
    )

  Observable.from(function* (){ yield 9; })
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Observable.from([10, 20, 30])
    )
    .subscribe(console.log)

  Array.of(1, 2, 3)
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Array.of(10, 20, 30)
    )

  Observable.interval(500)
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Observable.of(10, 20, 30)
    )

  Observable.from(function* (){ yield 9; })
    .map(i => i * 2)
    .filter(i => i > 5)
    .concat(
      Observable.from([10, 20, 30])
    )

How do I find my magical operator?

Marbles Diagrams

Animated Diagrams

Let's code!

Typeahead Search

Reactive Patterns

Immutability!

Every state must be part of the flow!

NEVER subscribe inside another subscribe!


  @Component()
  export class UserAddressComponent {

    constructor (
      user: UserService,
      address: AddressService,
    ) {
      user.getCurrentUser().subscribe(user => {



      })
    }
    
  }

  @Component()
  export class UserAddressComponent {

    constructor (
      user: UserService,
      address: AddressService,
    ) {
      user.getCurrentUser().pipe(

      ).subscribe(user => {
        this.address = address;
      })
    }
    
  }

  @Component()
  export class UserAddressComponent {

    constructor (
      user: UserService,
      address: AddressService,
    ) {
      user.getCurrentUser().subscribe(user => {
        address.getAddressFromUser(user).subscribe(address => {
          this.address = address;
        })
      })
    }
    
  }

  @Component()
  export class UserAddressComponent {

    constructor (
      user: UserService,
      address: AddressService,
    ) {
      user.getCurrentUser().pipe(
        mergeMap(user => this.address.getAddressFrom(user))
      ).subscribe(address => {
        this.address = address;
      })
    }
    
  }

Never forget to unsubscribe!

But actually avoid do it manually!

Use Pipe Async every time the data stream goes to the template!

In all other times try to reactively unsubscribe from streams!


  @Component()
  export class MyComponent {

    ngOnInit() {
      interval(1000)
        .subscribe(i => console.log(i));
    }

  }

  @Component()
  export class MyComponent {

    unsubscribe = new Subject();

    ngOnInit() {
      interval(1000)

        .subscribe(i => console.log(i));
    }

    ngOnDestroy() {
      this.unsubscribe.next();
      this.unsubscribe.complete();
    }
    
  }

  @Component()
  export class MyComponent {

    unsubscribe = new Subject();

    ngOnInit() {
      interval(1000)
        .pipe(takeUntil(this.unsubscribe))
        .subscribe(i => console.log(i));
    }

    ngOnDestroy() {
      this.unsubscribe.next();
      this.unsubscribe.complete();
    }
    
  }

Building a Reactive Architecture!

Standing on the Shoulder of Giants

Capture all changes to an application state as a sequence of events.

FOWLER, Martin. 2005

Let's model the state change as a sequence of immutable events!

Every event describe just the change to the state, not the current state!

The current state can just be discovery after execute all the chain of events!

How to use that idea at the real world?

Command Query Responsibility Segregation

FOWLER, Martin. 2011

It is an implementation of Event Sourcing

It's segregate the responsibility of the reader and the writer

Also segregate the state maintenance from side effects

Let's code!

Simple Counter

Complex Counter

We just recreated Redux!

NGRX

What about the

side effects?

The original Redux does not implements CQRS completely

@ngrx/effects

RxJS powered side effect model

redux-observable

Compose and cancel async actions to create side effects and more.

References

Thanks! =)

Workshop: Advanced RxJS patterns to reactive interfaces

By William Grasel

Workshop: Advanced RxJS patterns to reactive interfaces

Reactive programming is super flexible and powerful, but it is also hard to master! In this Workshop, we're are going to learn about common reactive smells and how to avoid them, and even better, were are going to learn the best patterns to reactively compose the most difficult interfaces with pure RxJS!

  • 1,551