2017年3月11日 星期六

[RxJS] switch and switchMap

 rxjs    switch     map    switchMap


Introduction


switch

Transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.



switchMap

= map + switch



switch sample


Let’s create a sample with this requirement:

Show a user’s last mouse position.


observable$ = Rx.Observable.fromEvent(document.body, 'mousemove')
                  .map(m=> "X:"+ m.x + ", Y:"+m.y);

 subscription$ = observable$.subscribe(position=>console.log(position));


Demo






Now let’s specify the requirement as …

Show a user’s last mouse position when he/she stop moving it.

Okay, this time we don’t want to show every position with the Observable sequence but only the LAST one.

We will use map, delay and switch to finish this job.

observable$ = Rx.Observable.fromEvent(document.body, 'mousemove')
                  .map(m=> "X:"+ m.x + ", Y:"+m.y);

 subscription$ = observable$
                 .map(position=> Rx.Observable.of(position).delay(2000))
                 .switch()
                 .subscribe(position=>console.log(position));

The following sequence picture shows how the above codes works.






Demo





switchMap sample


switch = map + switch

So we can update the above sample codes to

observable$ = Rx.Observable.fromEvent(document.body, 'mousemove')
                  .map(m=> "X:"+ m.x + ", Y:"+m.y);

 subscription$ = observable$
                 .switchMap(position=> Rx.Observable.of(position).delay(2000))
                 .subscribe(position=>console.log(position));



Sample

We will make another practice on the searching product (again!).
We would like to search the products when the user input some keywords.





ngAfterViewInit() {
    const elKeyword = document.getElementById('keyword');
    const keyups$ = Observable.fromEvent(elKeyword, 'keyup').map((e: any) => e.target.value);
    keyups$.subscribe((keyword: string) => {
      console.log("Searching : "+ keyword);
    })
  }

The above codes will make a disaster for searching every words we key in…




Yes! We could use switchMap and delay for just taking the last keywords and search it.

ngAfterViewInit() {
    const elKeyword = document.getElementById('keyword');
    const keyups$ = Observable.fromEvent(elKeyword, 'keyup').map((e: any) => e.target.value);
    keyups$.switchMap(this.delaySearch).subscribe((keyword: string) => {
      console.log("Searching : "+ keyword);
      this.products$ = this.prodSvc.search(keyword);
    })
  }

private delaySearch(keyword: string): Observable<string> {
    //return observale
    return Observable.of(keyword).delay(1000);

    //Or return promise
    // return new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve(keyword);
    //   }, 1000);
    // });
  }


Demo




Reference




沒有留言:

張貼留言