A specific use example of rxjs combinelate operator

Posted by j0hn_ on Mon, 31 Jan 2022 08:42:24 +0100

CombineLatest Usage scenarios:

This operator is best used when you have multiple, long-lived observables that rely on each other for some calculation or determination.

When there are multiple Observable objects that live for a long time and depend on each other to complete some calculation logic, CombineLatest is suitable

When any observable emits a value, emit the last emitted value from each.

In order to learn the usage of CombineLatest, I wrote the following small program:

import { Component, OnInit, Inject } from '@angular/core';
import { fromEvent, combineLatest } from 'rxjs';
import { mapTo, startWith, scan, tap, map } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-combine-latest',
  templateUrl: './combine-latest.component.html'
})
export class CombineLatestComponent implements OnInit {
  readonly document: Document;

  constructor(
    // https://github.com/angular/angular/issues/20351
    @Inject(DOCUMENT) document: any) {
      this.document = document as Document;
    }

  redTotal:HTMLElement;
  blackTotal: HTMLElement;
  total:HTMLElement;  
  test:HTMLElement;

  ngOnInit(): void {
    this.redTotal = this.document.getElementById('red-total'); 
    this.blackTotal = this.document.getElementById('black-total');
    this.total = this.document.getElementById('total');
    this.test = this.document.getElementById('test');

    combineLatest(this.addOneClick$('red'), 
    
    this.addOneClick$('black')).subscribe(([red, black]: any) => {
      this.redTotal.innerHTML = red;
      this.blackTotal.innerHTML = black;
      this.total.innerHTML = red + black;
    });

    fromEvent(this.test, 'click').pipe(map( event => event.timeStamp), mapTo(1)).subscribe((event) => console.log(event));
  }

  addOneClick$ = id =>
  fromEvent(this.document.getElementById(id), 'click').pipe(
    // map every click to 1
    mapTo(1),
    // keep a running total
    scan((acc, curr) => acc + curr, 0),
    startWith(0)
  );
}

effect:

  • Click the Red button, and the Red counter and Total counter will increase by 1
  • Click the Black button to add 1 to the Black counter and Total counter

combine input parameters: two Observable:

In my example, only the following statement is executed, and other IF branches are not included:

return fromArray(observables, scheduler).lift(new CombineLatestOperator(resultSelector))

First execute fromArray: the input is Array, which contains two elements:

fromArray: returns a new Observable. The input is subscribeToArray(input)

For the logical analysis of subscribeToArray, please refer to my article: Detailed analysis of subscribeToArray tool function in Rxjs.

Next, instantiate CombineLatestOperator:

Execute the lift operation to create a new Observable object:

The application calls the subscribe method of the Observable object:

The closure contains two Observable buttons: for red and black:

Follow the source attribute of Observable and_ subscribe to find all the operations passed in the Observable pipe:

First, use the first element of array as a parameter and call the subscriber function:

First execute mapTo(1) logic:

The destination of Maptosubscriber points to Scansubscriber:

scan.js internal implementation:

The calculator is a function customized by the application:

acc is scan JS, and curr is the current value.

The results of the current iteration are stored in the seed field of the Scan Operator as input for the next iteration:

The implementation of this Operator has a routine:

  1. The function of export is to pass in observable Code in pipe:

  1. call function implemented by operator
  2. ScanSubscriber inherits the subscriber and re implements it_ Next method. These are the differences between different subscribers_ On the next method.

After clicking the red or black button, the initial values of the two Observable are: 0, 0:

How is this 0, 0 generated?
Two empty objects: NONE

Is inserted here:

This merge map should be generated automatically by the framework:

The first element has been converted from an empty object to 0:

After this line of statement is executed, it becomes two zeros:

Copy an array using slice API:

It can be seen that the combinelate operator does not maintain the status itself, but waits for the input of scan in the maintenance status:

More Jerry's original articles are: "Wang Zixi":

Topics: angular