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

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

问题描述

我已经设置了一个 observable 服务来帮助我持久化数据,但是我需要一种方法来在数据等待来自 observable 时显示加载微调器.

我的服务:

导入 [...]从 'rxjs' 导入 { Observable, BehaviorSubject };@Injectable({提供在:'根'})出口类组织服务{私人组织 $ = 新的 BehaviorSubject([{[...]}]);构造函数(私有 http:HttpClient){这个.http.得到(环境.apicall).subscribe((data) => this.organisations$.next(data['organisations']));}getList(): Observable{返回 this.organisations$.asObservable();}

这是我的组件:

 导入 ...从 'uikit' 导入 UIkit;从 'rxjs' 导入 { Observable };@成分({选择器:应用程序组织列表",templateUrl: './organisationlist.component.html',styleUrls: ['./organisationlist.component.css']})导出类 OrganisationlistComponent 实现 OnInit {公共加载 = 真;公共组织$:Observable;构造函数(公共组织服务:组织服务){}ngOnInit() {this.getData().then(() => {this.loading = false;});}异步获取数据(){this.organisations$ = this.organisationsService.getList();}}

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

 <div *ngIf="loading" uk-spinner></div><div><ul class="uk-list"><li *ngFor="让组织的组织$ | async">{{ 机构名称 }}

显然,getData 函数虽然声明为异步,但实际上并不是异步并立即返回.所以 this.loading 是 'false' OnInit,因此它不显示.

周围有很多答案表明当订阅发生在组件中时这可能如何工作,但是因为这是服务中的共享数据,我找不到在设置之前等待数据的方法 this.loading 为 false.

非常感谢.

解决方案

感谢大家的回答,但这些建议都没有达到问题中概述的目的,但我确实研究了解决方案并最终得到了解决.我们开始:

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

然后我创建了一个 getter:

getLoading(): Observable{返回 this.loading$;}

然后我用 true 包装了 HTTP 调用,然后在订阅的第三个参数中将加载设置为 false(onCompleted 函数).

所以服务看起来像这样:

import { Observable, BehaviorSubject, of } from 'rxjs';@Injectable({提供在:'根'})出口类组织服务{私人组织 $ = 新的 BehaviorSubject([{[...]}]);//通过 BehaviorSubject 启动新的 Loading 变量,并从一开始就将其设置为true".public loading$ = new BehaviorSubject(true);构造函数(私有 http:HttpClient){//在我们开始 HTTP 调用之前再次将 loading$ 设置为 truethis.loading$.next(true);这个.http.get(environment.apicall).订阅(//onNext 方法,我们在这里获取数据(数据) =>this.organisations$.next(data['organisations']),//onError 方法(暂时空白)() =>{},//onComplated 方法,现在我们有了数据,我们可以将加载设置为 false() =>{this.loading$.next(false);});}getLoading(): Observable{返回 this.loading$;}getList(): Observable{返回 this.organisations$;}

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

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

 public loading$: Observable;公共组织$:Observable;构造函数(公共组织服务:组织服务){}ngOnInit() {this.getData();}异步获取数据(){//最初loading$将是真的,因为服务使它如此this.loading$ = this.organisationsService.getLoading();//当这完成时,loading$将通过服务设置为falsethis.organisations$ = this.organisationsService.getList();}

在我看来:

 

<div uk-spinner *ngIf="loading$ | async"></div><ul class="uk-list"><li *ngFor="让组织的组织$ | async">{{ 机构名称 }}

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.

My service:

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();
  }

Here's my component:

    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();
      }
}

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>

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.

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.

Many thanks.

解决方案

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:

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$; }

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$;
  }

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.

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();
      }

And in my view:

  <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 中的服务获取数据的 observable 时显示加载微调器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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