Home > front end >  How does combineLatest RxJS operator works when multiple observables emit values at the same time?
How does combineLatest RxJS operator works when multiple observables emit values at the same time?

Time:01-11

The RxJS Documentation states that

combineLatest Combines multiple Observables to create an Observable whose values are calculated from the latest values of each of its input Observables.

I want to understand how combineLatest works when multiple observables emit values at the same time?

If we look at the following code

import 'zone.js/dist/zone';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { timer, take, combineLatest } from 'rxjs';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `Hello`,
})
export class App {
  name = 'Angular';

  constructor() {
    const a$ = timer(0, 1000).pipe(take(5)); //Emit values after each second (total 5 values)

    const b$ = timer(0, 4000).pipe(take(5)); //Emit values after every 4 seconds (total 5 values)

    //Marble Diagram
    
    //0 1 2 3 4
    //0       1       2       3       4

    const result$ = combineLatest(a$, b$);

    result$.subscribe((val) => console.log(val));
  }
}

bootstrapApplication(App);

The output is as follows Output In the output above, at the 4th second the result$ observable outputs the values [4,0] and [4,1] simultaneously.

My question is, Why it does not prints only [4,1] since the combineLatest brings the latest value and "4" is the latest value from observable a$ and "1" is the latest value from observable b$ at the 4th second.

Link to Demo

Thanks in advance!

CodePudding user response:

You can use it like this:

import 'zone.js/dist/zone';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { timer, take, withLatestFrom } from 'rxjs';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `Hello`,
})
export class App {
  name = 'Angular';

  constructor() {
    const a$ = timer(0, 1000).pipe(take(5)); //Emit values after each second (total 5 values)

    const b$ = timer(0, 4000).pipe(take(5)); //Emit values after every 4 seconds (total 5 values)

    const result$ = a$.pipe(withLatestFrom(b$, (a, b) => [a, b]));

    result$.subscribe((val) => console.log(val));
  }
}

bootstrapApplication(App);

https://stackblitz.com/edit/angular-gsyobe?file=src/main.ts

CodePudding user response:

After each source emits at least one value, combineLatest emits whenever any of its source observables emit.

Even if two observables emit "at the same time" (I'm assuming you really mean in the same event loop), combineLatest will emit twice.

If you want to prevent emissions that occur in the same event loop, you could use debounceTime(0):

result$ = combineLatest(a$, b$).pipe(debounceTime(0));
  • Related