I've faced with a wierd case, when the async pipe doesn't work properly until I subscribe to the observable. Sources:
View of the component:
<div *ngIf="loading$ | async" fxLayout="row" fxLayoutAlign="center">
<span class="spinner">Loading...</span>
</div>
<h1>{{data$ | async}}</h1>
Component:
@Component({
selector: './tm-fake',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './fake.component.html'
})
export class FakeComponent implements OnInit {
constructor(
private _fs: FakeService
) {}
loading$ = new BehaviorSubject<boolean>(false);
data$ = this._fs.data$.pipe(indicateUntilNULL(this.loading$));
ngOnInit(): void {
this._fs.requestData();
//this.data$.subscribe(e => {});
}
}
Service:
@Injectable()
export class FakeService {
requestData(): void {
timer(2000).pipe(map(e => "data")).subscribe(e => this._data.next(e));
}
private readonly _data = new BehaviorSubject<string>(null);
readonly data$ = this._data.asObservable();
}
Operator:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
tap(e => indicator.next(!e))
);
}
I see the data
after 2 sec delay as excpected, but I didn't see a spinner during this delay. But if I uncomment the line this.data$.subscribe(e => {});
it starts to work fine. And I can't find the reason. Any ideas?
NB: loading$
emits correct values even this line is commented.
SOLUTION
Many thanks to @theMayer and his helpful advice. I just want to add the article, where the problem is explained in details. And according this article the most elegant solution is a delay(0)
operator:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
delay(0),
tap(e => indicator.next(!e))
);
}
{{ loading$ | async }}
? Because what you have should work even withonPush
. – martin<h1>{{loading$ | async}}</h1>
and it shows false all the time without subscription and works as expected with subscription - first it showstrue
, and then - after delayfalse
. – Don Tomato