NOTE: I observed it rxjs 5.5.12, 6.5.4, 6.5.5.
You may think that below two codes gives same results where s0 and s1 are instances of BehaviorSubject
.
Code-1
s1.pipe(
withLatestFrom(s0)
).subscribe(([v1, v0]) => {
console.log(v0, v1);
});
Code-2
s1.subscribe(v1 => {
s0.pipe(take(1)).subscribe(v0 => {
console.log(v0, v1);
});
});
In general case, it's true. But, in very unique situation, these gives different results.
Here is test code for it.
const s0 = new BehaviorSubject('A');
const s1 = new BehaviorSubject('a');
setTimeout(() => s0.next('B'), 500);
let i = 0;
s0.pipe( /* Part-A */
withLatestFrom(s1)
).subscribe(([v0, v1]) => {
console.log('s0-pipe: ', v0, v1);
s1.next(++i);
});
s1.pipe(
withLatestFrom(s0)
).subscribe(([v1, v0]) => {
console.log('s1-pipe: ', v0, v1);
});
s1.subscribe(v1 => {
s0.pipe(take(1)).subscribe(v0 => {
console.log('s1-sub: ', v0, v1);
});
});
This gives following result.
s0-pipe: A a
s1-pipe: A 1
s1-sub: A 1
s0-pipe: B 1
s1-pipe: A 2 <=
s1-sub: B 2
Two very interesting results are observed. s1-pipe: A a
and s1-sub: A a
are not shown. And s0
value at second s1-pipe
is not latest one!
To avoid this, I used below workaround at code Part-A
.
s0.pipe(
withLatestFrom(s1)
).subscribe(([v0, v1]) => {
console.log('s0-pipe: ', v0, v1);
setTimeout(() => s1.next(++i));
});
Then, it gives
s0-pipe: A a
s1-pipe: A a <=
s1-sub: A a <=
s1-pipe: A 1
s1-sub: A 1
s0-pipe: B 1
s1-pipe: B 2 <=
s1-sub: B 2
I think it's design of rxjs
. One thing I can learn from above is that it's very risky using circular withLatestFrom
at rxjs
.