Let's look at this piece of code:
let isNull = true;
const a$ = new Subject<void>();
const b$ = a$.pipe(
switchMap(() => {
if (!isNull)
return of(true).pipe(
tap(() => console.log('should be shared')),
delay(100) // (3)
);
else return of(null);
}),
shareReplay(1)
);
b$.subscribe((b) => console.log('1', b));
a$.next(); // (1)
b$.subscribe((b) => console.log('2', b));
isNull = false;
a$.next(); // (2)
b$.subscribe((b) => console.log('3', b));
The output is the following:
1 null
2 null
should be shared
3 null // *
1 true
2 true
3 true
Expected output:
1 null
2 null
should be shared
1 true
2 true
3 true
The line marked with *
is not desired and I am unsure where it comes from. I assume that the last Observable switchMap
returns is not the one updated by (2) but the old one from (1). If I remove the delay
at (3), the line marked with *
does not appear as expected. This sounds like a timing/ scheduling issue but I do not know a way
- to explain this exactly and to
- fix this elegantly and without unnecessary
next
ing
EDIT: Made the example more concise.
EDIT 2:
The reason why I am getting null
is that during the time of the third subscription, shareReplay
does not have the fresh value (true
) yet. Instead, it returns the stale value, which is null
. A partially correct workaround is to do this:
let isNull = true;
const a$ = new Subject<void>();
const b$ = a$.pipe(
switchMap(() => {
if (!isNull)
return of(true).pipe(
tap(() => console.log('should be shared')),
delay(100),
shareReplay(1)
);
else return of(null).pipe(shareReplay(1));
}),
share()
);
b$.subscribe((b) => console.log('1', b));
a$.next();
b$.subscribe((b) => console.log('2', b));
isNull = false;
a$.next();
b$.subscribe((b) => console.log('3', b));
// Output:
/*
1 null
should be shared
1 true
2 true
3 true
*/
But as you see, the output "2 null" is missing. So, I am still not sure how to solve this issue elegantly.