Angular 4+ 精细控制 http 调用以显示/隐藏加载器

Angular 4+ Granular control over http call to show / hide loader

我有一项服务进行 http 调用并将数据作为 Observable 返回,我将它分配给组件中的一个变量,如下所示

this.usersResponse$ = this.dataSvc.getUsers(pageNumber);

在 html 我正在做以下事情

<div *ngIf="usersResponse$ | async as userResponse; else loading">
    <ng-container>
        <ul>
            <li *ngFor="let user of userResponse.data" (click)="detail(user.id)">
                <img [src]="user.avatar" alt="">
                <p>{{ user.first_name }} {{ user.last_name }}</p>
            </li>
        </ul>
    </ng-container>    
</div>
<ng-template #loading>
    <app-loading></app-loading>
</ng-template>

我想要实现的是如何在 http 调用之前获得精细控制以显示加载器,然后让 http 调用取回数据并关闭加载器,这样 UI 就会跳动。

感谢您的帮助。

使用完整事件:

 this.showLoader=true;
this.usersResponse$ = this.dataSvc.getUsers(pageNumber);
this.usersResponse$.subscribe(null, null, () => 
this.showLoader=false);

在模板中

   <app-loading *ngIf="showLoader"></app-loading>

你可以在简单的 monad 的帮助下让它成为反应式的:

https://www.npmjs.com/package/ng-loadable-content

import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';

@Injectable()
export class ObjectStore {

    private readonly _state = new BehaviorSubject<LoadableContent<UserResponse>>(LoadableContent.initial());
    readonly state$ = this._state.asObservable();

    constructor(private readonly dataSvc: RemoteService) {
    }

    reload(pageNumber: number) {
        this._state.next(LoadableContent.loading());
        this.dataSvc.getUsers(pageNumber)
            .subscribe(
                res => this._state.next(LoadableContent.loaded(res)),
                e => this._state.next(LoadableContent.error(e))
            );
    }

}

控制器:

import {Observable} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';

@Component({
    selector: 'app-object',
    templateUrl: './object.component.html',
    providers: [ObjectStore]

})
export class ObjectComponent {

    readonly state$: Observable<LoadableContent<UserResponse>>;

    constructor(private readonly objectStore: ObjectStore) {
        this.state$ = objectStore.state$;
        this.objectStore.reload(1);
    }

}

模板:

<div>
    
    <ng-container *ngIf="state$ | async as state">
        <div *ngIf="state | loaded as dto">
          <ul>
            <li *ngFor="let user of dto.data" (click)="detail(user.id)">
                <img [src]="user.avatar" alt="">
                <p>{{ user.first_name }} {{ user.last_name }}</p>
            </li>
          </ul>
        </div>
        <app-loading *ngIf="state | loading"></app-loading>
        <div *ngIf="state | loadError">
            Failed to load
        </div>
    </ng-container>

</div>