В Документации RxJS говорится, что
combLatest Объединяет несколько Observable для создания Observable, значения которого рассчитываются на основе последних значений каждого из его входных Observables.
Я хочу понять, как работает combLatest, когда несколько наблюдаемых выдают значения одновременно?
Если мы посмотрим на следующий код
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.info(val));
}
}
bootstrapApplication(App);
Вывод выглядит следующим образом Выход В приведенном выше выводе на 4-й секунде результат $ observable выводит значения [4,0] и [4,1] одновременно.
Мой вопрос: почему он не печатает только [4,1], так как combLatest приносит последнее значение, а "4" - это последнее значение из наблюдаемого a$, а "1" - последнее значение из наблюдаемого b$ на 4-й секунде. .
Ссылка на демо
Заранее спасибо!
Вы можете использовать его следующим образом:
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.info(val));
}
}
bootstrapApplication(App);
Https://stackblitz.com/edit/angular-gsyobe?file=src/main.ts
Это обеспечивает поведение, отличное от combineLastest. combineLastest будет излучать, когда a$ или b$ излучает. Это решение излучает только тогда, когда излучает a$.
Это на самом деле не отвечает на вопрос. ОП спросил, почему его код ведет себя именно так. Кроме того, при размещении кода в ответе всегда полезно объяснить код, т. е. почему он лучше, как он решает конкретную проблему и т. д.
Я разделяю мысли БиззиБоба и Черилла. В любом случае спасибо за попытку!
После того, как каждый источник выдает хотя бы одно значение, combLatest выдает каждый раз, когда выдает любой из его исходных наблюдаемых.
Даже если два наблюдаемых излучают «одновременно» (я предполагаю, что вы действительно имеете в виду в одном и том же цикле событий), combineLatest будет излучаться дважды.
Если вы хотите предотвратить выбросы, которые происходят в том же цикле событий, вы можете использовать debounceTime(0):
result$ = combineLatest(a$, b$).pipe(debounceTime(0));
Работает отлично! Спасибо за ответ по существу.
Чтобы расширить хороший ответ BizzyBobs: поскольку JS по своей природе является однопоточным, два события не могут произойти в одно и то же время. Во-вторых, при использовании таймеров у вас всегда есть допуск. Интервал между двумя выбросами timer(0,. 1000) никогда не равен ровно 1000 мс, а хотя бы 1000 мс.