如何在等待可观察到的从Angular中的服务获取数据时显示加载微调器 [英] How to show a loading spinner while waiting on an observable getting data from a service in Angular

查看:25
本文介绍了如何在等待可观察到的从Angular中的服务获取数据时显示加载微调器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了一个可观察的服务来帮助我保留数据,但是我需要一种方法来在数据正等待来自可观察的数据时显示加载微调器.

I have set up an observable service that helps me persist data, but I need a way to show a loading spinner while the data is waiting to come from the observable.

我的服务:

imports [...]

import { Observable, BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class OrganisationsService {
  private organisations$ = new BehaviorSubject<Organisation[]>([
    {
      [...]
    }
  ]);

  constructor(private http: HttpClient) {
    this.http
      .get(
        environment.apicall
      )
      .subscribe((data) => this.organisations$.next(data['organisations']));
  }

  getList(): Observable<Organisation[]> {
    return this.organisations$.asObservable();
  }

这是我的组成部分:

    imports ...

    import UIkit from 'uikit';
    import { Observable } from 'rxjs';

    @Component({
      selector: 'app-organisationlist',
      templateUrl: './organisationlist.component.html',
      styleUrls: ['./organisationlist.component.css']
    })
    export class OrganisationlistComponent implements OnInit {

      public loading = true;

      public organisations$: Observable<Organisation[]>;

      constructor(public organisationsService: OrganisationsService) {}

      ngOnInit() {
        this.getData().then(() => {
          this.loading = false;
        });
      }

      async getData() {
        this.organisations$ = this.organisationsService.getList();
      }
}

这是我的布局(使用Uikit):

Here's my layout (uses Uikit):

  <div *ngIf="loading" uk-spinner></div>
  <div>
    <ul class="uk-list">
      <li *ngFor="let organisation of organisations$ | async">
        {{ organisation.name }}
      </li>
    </ul>
  </div>

很明显,getData函数尽管已声明为异步,但实际上并没有异步并立即返回.因此this.loading为OnInit'false',因此它不会显示.

Obviously, the getData function, although declared async, is not actually async and returns immediately. So this.loading is 'false' OnInit, and therefore it doesn't show.

周围有很多答案,显示了在组件中进行订阅时这可能如何工作,但是由于这是服务中的共享数据,因此我找不到在设置this.loading之前等待数据的方法.为假.

There are plenty of answers around that show how this might work when the subscription happens in the component, but because this is shared data in a service, I can't find a way to wait on the data before setting this.loading to false.

非常感谢.

推荐答案

谢谢大家的答复,但这些建议均不适用于问题中概述的目的,但我确实致力于解决方案的制定,最终得到了解决方案.我们开始:

Thank you all for your responses, but none of these suggestions worked for the purposes outlined in the question, but I did work on a solution and eventually got one working. Here we go:

在服务中,我创建了一个名为loading$的新Observable并将其设置为new BehaviorSubject<boolean>(true);

In the service I created a new Observable called loading$ and set it up as a new BehaviorSubject<boolean>(true);

然后我创建了一个吸气剂:

Then I created a getter:

getLoading(): Observable<boolean> { return this.loading$; }

getLoading(): Observable<boolean> { return this.loading$; }

然后,我用true包裹HTTP调用,然后在订阅的第3个参数( onCompleted 函数).

Then I wrapped the HTTP call with a true then set loading to false in the 3rd argument on the subscription (the onCompleted function).

所以服务看起来像这样:

So the service looks like this:

import { Observable, BehaviorSubject, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class OrganisationsService {
  private organisations$ = new BehaviorSubject<Organisation[]>([
    {
      [...]
    }
  ]);

  //initiate the new Loading variable via BehaviorSubject and set it to "true" from the beginning.
  public loading$ = new BehaviorSubject<boolean>(true);

  constructor(private http: HttpClient) {

    //set the loading$ to true again just before we start the HTTP call
    this.loading$.next(true);


    this.http
      .get(environment.apicall)
      .subscribe(

        //onNext method, where we get the data
        (data) => this.organisations$.next(data['organisations']),

        //onError method (Blank for now)
        () => {},

        //onComplated method, now that we have the data we can set the loading to false
        () => {
          this.loading$.next(false);
        }
      );
  }

  getLoading(): Observable<boolean> {
    return this.loading$;
  }

  getList(): Observable<Organisation[]> {
    return this.organisations$;
  }

请注意,在HTTP调用的subscription方法中,我添加了一个空白的第二个方法(这是用于onError),然后在第3个方法中,我添加了一个将加载设置为false的函数:this.loading$.next(false); .这意味着订阅完成后,Loading现在将为false.

Notice in the subscribe method on the HTTP call, I'm adding a blank second method (This is for onError) and then in the 3rd method, I've added a function to set the loading to false: this.loading$.next(false); . This means that Loading will now be false when the subscription is complete.

然后在我的组件中,获得loading$订阅:

Then in my component, I get the loading$ subscription:

      public loading$: Observable<boolean>;
      public organisations$: Observable<Organisation[]>;

      constructor(public organisationsService: OrganisationsService) {}

      ngOnInit() {
        this.getData();
      }

      async getData() {

        //initially loading$ will be true because the service makes it so
        this.loading$ = this.organisationsService.getLoading();

        //when this completes, loading$ will be set to false via the service
        this.organisations$ = this.organisationsService.getList();
      }

在我看来:

  <div>
    <div uk-spinner *ngIf="loading$ | async"></div>
    <ul class="uk-list">
      <li *ngFor="let organisation of organisations$ | async">
        {{ organisation.name }}
      </li>
    </ul>
  </div>

这篇关于如何在等待可观察到的从Angular中的服务获取数据时显示加载微调器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆