Angular – 在服务调用后执行操作

huangapple go评论52阅读模式
英文:

Angular - action after service call is made

问题

我在使用Angular 14,加载一个包含内容的页面。然而,其中一些内容是从一个出站服务调用中检索的,而在内容加载时我有一个加载屏幕。

我在我的加载旋转器上使用了*ngIf语句,并在进行调用时将该变量设置为true。当内容返回时,我将变量设置为false,这应该显示完整的内容。

我看到的行为是屏幕加载,旋转器消失,然后几秒钟后我的内容出现。

我正在研究一些Angular生命周期钩子,我想知道是否有办法在所有我的ngOnInit()操作完全完成后将该变量设置为false。

提前感谢。

英文:

Im working in Angular 14, and Im loading a page with content. Some of the content though, is retrieved from an outbound service call, and I have a loading screen while the content is loading.

I have an *ngIf statement on my loading spinner, and I set that variable to true while I make my call. When the content comes back, I set the variable to false, which should now display the full content.

The behavior Im seeing is that the screen loads, and spinner disappears and then a few seconds later my content pops up.

Im looking into some of these Angular lifecycle hooks, and Im wondering if there's a way to use these to set that variable to false once all my ngOnInit() operations are fully completed.

Thanks in advance.

答案1

得分: 1

在这方面没有内置的方法,主要是因为你的 ngOnInit() 可能包含一个异步函数,而 Angular 无法保证该函数何时完成(除非将开发者强制进入某种模式,在 ngOnInit() 中返回一个 Promise/Observable等)。

但是,你可以自己构建一个等效的方法(不在 ngOnInit 中,而是在你正在使用的函数内部)。这实际上比绑定到 Angular 生命周期钩子更灵活,因为你可以在任何地方(以及任何时候)设置你的加载状态以部署你的函数。

在大多数应用程序中,你将有一些异步到达的数据源,因此通常你会使用 RxJS 来组合所有异步源并在所有数据源成功返回或出错时更新加载状态。

例如:

synchronous example

export class YourComponent {
  ngOnInit() {
    this.setupPage();
  }

  setupPage(): void {
    this.isLoading = true;
    this.yourSyncFn1();
    this.yourSyncFn2();
    this.yourSyncFn3();
    this.isLoading = false;
  }
}

asynchronous example

export class YourComponent {
  ngOnInit() {
    this.setupPage();
  }

  setupPage(): void {
    this.yourAsyncFns$().subscribe();
    this.yourSyncFn1();
    this.yourSyncFn2();
  }

  yourAsyncFn1$(): Observable<[DataOne[], DataTwo[]]> {
    yourAsyncData1$: Observable<DataOne[]> = this.dataService.getData1$().pipe(catchError(() => []));
    yourAsyncData2$: Observable<DataTwo[]> = this.dataService.getData2$().pipe(catchError(() => []));

    return defer(
      () => {
        this.isLoading = true; // This will be set at the moment this.yourAsyncFn1$() is subscribed to

        return forkJoin([yourAsyncData1$, yourAsyncData2$])
          .pipe(
            finalize(
              () => {
                this.isLoading = false; // This will be set at the moment your forkJoin completes
              }
            )
          );
      }
    )
  }
}
英文:

There isn't an inbuilt way of doing this, mainly because your ngOnInit() could contain an async function and Angular can't guarantee when that function has finished (without forcing the developer into some pattern where they have to return a Promise/Observable from within ngOnInit() etc).

However, you can build an equivalent yourself (not in ngOnInit, but within the functions you are using). This is actually more flexible than being tied to an Angular lifecycle hook as you can set your loading state wherever (and whenever) you want to deploy your functions.

In most applications, you will have some source of data arriving asynchronously, so typically you would use RxJS to combine all of your asynchronous sources and update your loading state when all data sources have either returned successfully or errored.

For example:

synchronous example

export class YourComponent {
  ngOnInit() {
    this.setupPage();
  }

  setupPage(): void {
    this.isLoading = true;
    this.yourSyncFn1();
    this.yourSyncFn2();
    this.yourSyncFn3();
    this.isLoading = false;
  }
}

asynchronous example

export class YourComponent {
  ngOnInit() {
    this.setupPage();
  }

  setupPage(): void {
    this.yourAsyncFns$().subscribe();
    this.yourSyncFn1();
    this.yourSyncFn2();
  }

  yourAsyncFn1$(): Observable&lt;[DataOne[], DataTwo[]]&gt; {
    yourAsyncData1$: Observable&lt;DataOne[]&gt; = this.dataService.getData1$().pipe(catchError(() =&gt; []));
    yourAsyncData2$: Observable&lt;DataTwo[]&gt; = this.dataService.getData2$().pipe(catchError(() =&gt; []));

    return defer(
      () =&gt; {
        this.isLoading = true; // This will be set at the moment this.yourAsyncFn1$() is subscribed to

        return forkJoin([yourAsyncData1$, yourAsyncData2$])
          .pipe(
            finalize(
              () =&gt; {
                this.isLoading = false; // This will be set at the moment your forkJoin completes
              }
            )
          );
      }
    )
  }
}

huangapple
  • 本文由 发表于 2023年2月23日 21:39:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定