【问题标题】:Angular 4+ Granular control over http call to show / hide loaderAngular 4+ 对 http 调用的粒度控制以显示/隐藏加载器
【发布时间】:2019-05-07 12:24:56
【问题描述】:

我有一个服务进行 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 跳跃。

感谢您的帮助。

【问题讨论】:

    标签: angular rxjs6


    【解决方案1】:

    您可以借助简单的 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>
    

    【讨论】:

      【解决方案2】:

      使用完成事件:

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

      在模板中

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

      【讨论】:

      • 当我们订阅 userResponse$ observable 时,我们是否必须在组件销毁时手动取消订阅?
      • 他的回答暗示当观察者完成时 showLoader 将被设置为 false。当观察者完成时,订阅将不再处于活动状态,因此如果满足这些条件,则无需手动取消订阅。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 2019-06-12
      • 2015-07-22
      • 1970-01-01
      相关资源
      最近更新 更多