RxCoffeeShop

@ktrz__  |      /ktrz

20.03.2019, Angular Brisbane

Chris Trześniewski

Senior Frontend Developer @Scalac

https://slides.com/ktrz/ng-brisbane-rx-cs

What's an Observable

 

  • Stream
  • Promise on steroids
  • Function that tie observer to a producer

Data delivered over time

 

Operators

Operators

const source$: Observable<number> = timer(1000);

const result$: Observable<number> = source$
  .pipe(
    filter(v => v % 3 === 1),
    map(v => v * 7)
  );

Enough with the theory

 

How can we use it?

The way of coffee

 

  • Make order
  • Barista picks up order
  • Coffee brewing
  • Optionally
    • Heat milk
    • Add milk
  • I pick up coffee

We can code that!

 

Order board

<button (click)="clicks$.next($event)">
  Add order
</button>
<app-coffee-items [items]="state$ | async">
</app-coffee-items>
export class AppComponent {
  clicks$: Subject<Event> = new Subject();

  state$: Observable<CoffeeRequest[]> = of();
}
  clicks$: Subject<Event> = new Subject();
  coffeeReqs$: Observable<CoffeeRequest> =
    this.clicks$.pipe(
      map(idGenerator()), // generates unique id
      map(id => ({
        id: id,
        status: CoffeeRequestStatusValue.requested,
      }))
    );

  state$: Observable<CoffeeRequest[]> =
    this.coffeeReqs$.pipe(
      
      ???

    );
  clicks$: Subject<Event> = new Subject();
  coffeeReqs$: Observable<CoffeeRequest> =
    this.clicks$.pipe(
      map(idGenerator()), // generates unique id
      map(createCoffeeRequest), 
      // maps to {id, status: requested}
    );

  state$: Observable<CoffeeRequest[]> =
    this.coffeeReqs$.pipe(
      
      ???

    );

  state$: Observable<CoffeeRequest[]> =
    this.coffeeReqs$.pipe(
      scan((
        state: CoffeeRequest[],
        val: CoffeeRequest) => [...state, val],
        []),
    );

  state$: Observable<CoffeeRequest[]> =
    this.coffeeReqs$.pipe(
      scan((
        state: CoffeeRequest[],
        val: CoffeeRequest) => [...state, val],
        []),
      startWith([])
    );
  coffeeReqs$: Observable<CoffeeRequest> =
    this.clicks$.pipe(
      map(idGenerator()), // generates unique id
      map(id => ({
        id: id,
        status: CoffeeRequestStatusValue.requested,
      }))
    );

  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(assignBarista());
export class AppComponent {
  coffeeReqs$: Observable<CoffeeRequest> =
    prevCoffeeRequest$.pipe(share());

  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(
      delay(1000),
      map((request: CoffeeRequest): CoffeeRequest => ({
        ...request,
        status: CoffeeRequestStatusValue.making,
      }))
    );

  





  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(
      delay(1000),
      map((request: CoffeeRequest): CoffeeRequest => ({
        ...request,
        status: CoffeeRequestStatusValue.making,
      }))
    );

  const setStatus = (status: CoffeeRequestStatusValue) =>
    map((request: CoffeeRequest): CoffeeRequest => ({
      ...request,
      status,
    }));

  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(
      delay(1000),
      



    );

  const setStatus = (status: CoffeeRequestStatusValue) =>
    map((request: CoffeeRequest): CoffeeRequest => ({
      ...request,
      status,
    }));

  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(
      delay(1000),
      setStatus(CoffeeRequestStatusValue.making)
    );
 
  state$: Observable<CoffeeRequest[]> =
    merge(this.coffeeReqs$, this.coffeeMaking$).pipe(
      scan((
        state: CoffeeRequest[],
        val: CoffeeRequest) => [...state, val],
        []),
      startWith([])
    );
}
  coffeeReqs$: Observable<CoffeeRequest> =
    this.clicks$.pipe(
      map(idGenerator()), // generates unique id
      map(createCoffeeRequest), 
      // maps to {id, status: requested}
    );

  coffeeMaking$: Observable<CoffeeRequest> =
    this.coffeeReqs$.pipe(
      delay(1000),
      setStatus(CoffeeRequestStatusValue.making)
    );
 
  state$: Observable<CoffeeRequest[]> =
    merge(this.coffeeReqs$, this.coffeeMaking$).pipe(
      scan((
        state: CoffeeRequest[],
        val: CoffeeRequest) => [...state, val],
        []),
      startWith([])
    );
}
export class AppComponent {
  coffeeReqs$: Observable<CoffeeRequest> = /* */
  coffeeMaking$: /* */
 
  state$: Observable<CoffeeRequest[]> =
    merge(this.coffeeReqs$, this.coffeeMaking$).pipe(
      scan((
        state: { [key: number]: CoffeeRequest },
        val: CoffeeRequest) => ({
          ...state,
          [val.id]: val,
        }),
        {}),
      map(state => Object.keys(state)
        .map(key => state[key])
        .filter(v => !!v)),
      startWith([])
    );
}
  coffeeMaking$: Observable<CofReq> =
    this.coffeeReqs$.pipe(
      delay(1000),
      setStatus(CoffeeRequestStatusValue.making)
    );

Operators

export interface OperatorFunction<T, R> {
  (source: Observable<T>): Observable<R>;
}

const noopOperator = <T>(source: Observable<T>) => source;
const filterAndMultiply = (source: Observable<number>) =>
  source.pipe(
    filter(v => v % 3 === 1),
    map(v => v * 7)
  );
const multiplyBy7 = map(v => v * 7)
const multiplyBy7 = (source: Observable<number>) =>
  source.pipe(
    map(v => v * 7)
  );
  coffeeMaking$: Observable<CofReq> =
    this.coffeeReqs$.pipe(this.assignBarista());
 
  assignBarista(): OperatorFunction<CofReq, CofReq> {
    return (source: Observable<CoffeeRequest>) =>
      source.pipe(
        delay(1000),
        setStatus(CoffeeRequestStatusValue.making)
      );
  }
  /* makeCoffee, pickupCoffee */
state$: Observable<CofReq[]> =
    merge(
      this.coffeeReqs$, this.coffeeMaking$,
      this.coffeeDone$, this.coffeePickedUp$)
    .pipe(/* scan, map */)
  coffeeMaking$: Observable<CofReq> =
    this.coffeeReqs$.pipe(
      delay(1000),
      setStatus(CoffeeRequestStatusValue.making)
    );
  coffeeDone$: Observable<CofReq> =
    this.coffeeMaking$.pipe(this.makeCoffee());
  coffeePickedUp$: Observable<CofReq> =
    this.coffeeDone$.pipe(this.pickupCoffee());

What more...

Live coding

So now...

let's enjoy our coffee...

... as a stream

Thank you!

 

Any question?

 

RxCoffeeShop Angular Brisbane

By Chris Trześniewski

RxCoffeeShop Angular Brisbane

  • 121
Loading comments...

More from Chris Trześniewski