[RxJS in Angular] - common operators

        RxJS provides many operators to operate and control the data flow (Observable). In  the article [RxJS in Angular] - Creating Data Streams,  the method of creating data streams is introduced, and the relevant operators will not be described here. This article only introduces commonly used operators for the processing of data in the data stream and the stream as a whole.

1. Operators for streaming data

map operator

        Use the map operator to process the data generated each time in the data stream, map(val: funcion(val: R):R)   , code example:

import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
    
 let ob: Observable<number> = from([80, 90, 100]);
 let fn = (num: number) => num * 2;
 ob.pipe(map(fn)).subscribe(d => { console.log(d); });
 // 输出:
 // 160
 // 180
 // 200

tap operator

        Use the tap operator to listen to each emitted value on the source Observable, do additional processing, but return the same source Observable. Code example:

    import { from, Observable } from 'rxjs';
    import { tap } from 'rxjs/operators';
    
    let ob: Observable<number> = from([1, 2, 3]);
    ob.pipe(
      tap(d => { console.log(`tap log ${d}`); })
    ).subscribe(d => { console.log(d); });
 // 输出:
 // tap log 1
 // 1
 // tap log 2
 // 2
 // tap log 3
 // 3

scan operator

        Use the scan operator to count up the number of times data is generated, scan(accumulator: funcion(acc: R):R, seed: R) , code example:

    import { from, Observable } from 'rxjs';
    import { scan } from 'rxjs/operators';

    let ob: Observable<string> = from(["a", "b", "c"]);
    ob.pipe(scan(d => d + 10, 15)).subscribe(d => {
      console.log(d);
    });
    // 输出:
    // 25
    // 35
    // 45

throttleTime operator

        Use the throttleTime operator to emit a value from the source data stream, then ignore subsequent emitted source values ​​for a set amount of time, and repeat the process.

The flow diagram corresponding to         throttleTime(duration: number) :

         [RxJS in Angular]- The example in the overview that the control button can be clicked at most once in a second uses the throttleTime operator:

  import { fromEvent } from 'rxjs';
  import { scan, throttleTime } from 'rxjs/operators';
  
  /**
   * 绑定按钮点击事件
   */
  bindBtn2CLick() {
    const button = document.querySelector('#btn2') as HTMLElement;
    fromEvent(button, 'click').pipe(
        throttleTime(1000), 
        scan(count => count + 1, 0)
    ).subscribe(count => {
      console.log(`按钮2点击了 ${count} 次`);
    });
  }

auditTime operator

        Use the auditTime operator to ignore the source value for a set amount of time, then emit the latest value from the source Observable, and repeat the process.  

        The flow diagram corresponding to auditTime(duration: number):

         auditTime is like throttleTime, but sends the last value of the silence time window instead of the first. As long as audit's internal timer is disabled, it emits the latest value of the source Observable on the output Observable, and ignores the source value when the timer is enabled. Initially, the timer is disabled. As soon as the first value is reached, the timer is enabled. After the duration elapses, the interval is disabled, the output Observable emits the latest value, and the process repeats itself.

debounceTime operator

        Use the debounceTime operator to emit a value from the source Observable only after a specified amount of time has elapsed without emitting another source value. The corresponding flow diagram:

         One of the most commonly used scenarios of the debounceTime operator is input association. The following example demonstrates the input association query after stopping input for 50 milliseconds:

    const input = fromEvent(document.querySelector('input'), 'input');
    input.pipe(
      debounceTime(200),
      map(event => event.target.value),
    ).subscribe(value => {
      console.log(value);
    });

skip operator

        Use the skip operator to skip the first N values ​​(N = count) emitted by the source Observable, and the flow diagram corresponding to skip(count: number) :

 skipUntil operator

        Use the skipUntil operator to skip the value emitted by the source Observable until another Observable emits a value

The flow diagram corresponding to skipUntil(notifier: Observable) :

 take operator

        Use the take operator to emit only the N values ​​(N = count) originally emitted by the source Observable.

        The flow diagram corresponding to take(count: number) :

 takeUntil operator

        Use the takeUntil operator to emit values ​​emitted by the source Observable until another Observable emits values.

        The flow diagram corresponding to takeUntil(notifier: Observable):

         More commonly used operators for streaming data include: first() last(), etc., which will not be listed here. You can refer to the official documentation to learn: RxJS official documentation. It should be noted that in the Angular framework for The operators of streaming data are all written in the pipe() method, which is slightly different from the syntax of the official website.

2. Processing for the overall flow

zip operator

        Multiple Observables are combined using the zip operator to create an Observable whose values ​​are computed sequentially from the values ​​of all input Observables. If the last argument is a function, this function is used to calculate the final emitted value. Otherwise, an array containing all input values ​​in order is returned.

    import { Observable, from, zip } from 'rxjs';
    
    let obName: Observable<string> = from(["Lucy", "LiLei", "HanMeiMei"]);
    let obScore: Observable<number> = from([80, 90, 100]);
    zip(obName, obScore).subscribe(([name, score]) => {
      console.log(`name: ${name}, score: ${score}.`)
    });
    // 输出:
    // name: Lucy, score: 80.
    // name: LiLei, score: 90.
    // name: HanMeiMei, score: 100.

        The case where the last parameter of zip is a function:

    import { Observable, from, zip } from 'rxjs';
     
    let obName: Observable<string> = from(["Lucy", "LiLei", "HanMeiMei"]);
    let obScore: Observable<number> = from([80, 90, 100]);
    let fn = (name: any, score: any) => {
      return `name: ${name}, score: ${score}.`;
    };
    zip(obName, obScore, fn).subscribe((d) => { console.log(d); });
    // 输出:
    // name: Lucy, score: 80.
    // name: LiLei, score: 90.
    // name: HanMeiMei, score: 100.

        When using the zip operator, the total data stream will be triggered to generate data only when each data stream has data, such as obScore = from([80, 90]); in the above example, there will only be two data output, only the first two lines will be printed.

merge operator

        Use the merge operator to merge multiple data streams into one data stream, and then send them in sequence:

  import { timer, Observable, merge } from 'rxjs';
  import { map } from 'rxjs/operators';
    
    let obA: Observable<any> = timer(10000, 2000).pipe(map(d => `Observable A : ${d}`));
    let obB: Observable<any> = timer(2000, 2000).pipe(map(d => `Observable B : ${d}`));
    merge(obA, obB).subscribe(d => { console.log(d); });
    // 延迟1秒后每间隔2秒输出
    // Observable A : 0
    // Observable B : 0
    // Observable A : 1
    // Observable B : 1
    // ...

concat operator

        The concat operator can be used to concatenate the data of two data streams together as one data stream and emit the data in concatenated order:

  import { timer, Observable, concat } from 'rxjs';
  
    let obA: Observable<number> = from([1, 2, 3]);
    let obB: Observable<number> = from([4, 5, 6]);
    concat(obA, obB).subscribe(d => { console.log(d); });
    // 输出
    // 1
    // 2
    // 3
    // 4
    // 5
    // 6

        When using the concat operator, the data in the subsequent data stream must wait until the data in the previous data stream is sent before it can be sent:

  import { timer, Observable, concat } from 'rxjs';
  import { map } from 'rxjs/operators';
  
    let obA: Observable<any> = timer(1000, 2000).pipe(map(d => `Observable A : ${d}`));
    let obB: Observable<any> = timer(2000, 2000).pipe(map(d => `Observable B : ${d}`));
    concat(obA, obB).subscribe(d => { console.log(d); });

        The above code will only print the information of Observable A, because obA has not been completed, so the data in obB cannot be emitted.

Guess you like

Origin blog.csdn.net/evanyanglibo/article/details/122394161