Я столкнулся со странным случаем, когда асинхронный канал не работает должным образом, пока я не подпишусь на наблюдаемое.Источники:
Вид компонента:
<div *ngIf="loading$ | async" fxLayout="row" fxLayoutAlign="center">
<span class="spinner">Loading...</span>
</div>
<h1>{{data$ | async}}</h1>
Компонент:
@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 => {});
}
}
Сервис:
@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();
}
Оператор:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
tap(e => indicator.next(!e))
);
}
Я вижу data
после 2-секундной задержки, как и ожидалось, но я не видел счетчика во время этой задержки.Но если я раскомментирую строку this.data$.subscribe(e => {});
, она начнет работать нормально.И я не могу найти причину.Есть идеи?
Примечание: loading$
выдает правильные значения, даже если эта строка закомментирована.
РЕШЕНИЕ
Большое спасибо @theMayer и его сотрудникамсовет.Я просто хочу добавить статью , где проблема подробно объясняется.И согласно этой статье самое элегантное решение - это оператор delay(0)
:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
delay(0),
tap(e => indicator.next(!e))
);
}