Reputation: 312
I'm new in Rxjs and I have faced with a strange behavior of BehaviorSubject with scan and combineLatest operator. Below the code of simple component:
import { Component, OnInit } from '@angular/core';
import { BehaviorSubject, of, combineLatest } from 'rxjs';
import { switchMap, scan} from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
stream1 = new BehaviorSubject('');
stream2 = new BehaviorSubject(0);
result: any;
counter = 1;
sub: any;
constructor() {}
ngOnInit() {
this.sub = this.stream2.pipe(
scan((acc, v) => [...acc, v], []),
);
this.result = this.stream1.pipe(
switchMap(data => combineLatest(of(data), this.sub))
).subscribe(val => console.log(val));
this.stream1.next('init');
this.stream2.pipe(scan((acc, v) => [...acc, v], [])).subscribe(val => console.log('Track Stream 2: ', val));
}
onClick() {
this.stream2.next(this.counter++);
}
onClick2() {
this.stream1.next('test ' + this.counter);
}
}
<button (click)="onClick()">Test</button>
<button (click)="onClick2()">Test2</button>
As result of "this.result" stream I expect array where the first value - the latest value from 'this.stream1' and the 2nd value is an array with all values which were collected by 'this.sub', but on fact from "this.sub" I get only the latest value, as if my scan operator was ignored.. See attached img:
Could you please explain how to reach desired result? Thank you all!
Ps. Angular v6.0.7 and RxJs v6.2.1
Upvotes: 1
Views: 2380
Reputation: 312
Seems like I found solution. I could fix it with shareReplay(0) operator, but I'm not sure if it the best solution, please correct me if so :)
ngOnInit() {
this.sup = this.stream2.pipe(
scan((acc, v) => [...acc, v], []),
shareReplay(0) // Solution
);
this.result = this.stream1.pipe(
switchMap(ud => combineLatest(of(ud), this.sup))
// withLatestFrom(this.sup)
).subscribe(val => console.log(val));
this.stream1.next('second');
this.stream2.pipe(scan((acc, v) => [...acc, v], [])).subscribe(val => console.log('Stream 2: ', val));
}
Upvotes: 2