在 Angular 11 中完成 Observable 和渲染后如何运行代码?

Posted

技术标签:

【中文标题】在 Angular 11 中完成 Observable 和渲染后如何运行代码?【英文标题】:How to run code after Obsevable AND rendering finished in Angular 11? 【发布时间】:2021-09-11 00:19:56 【问题描述】:

在我的 Angular 11 项目中,我有一个 Observable,它改变了视图并在渲染时需要一些时间。

类似这样的:

export class MyComponent implements OnInit 
  myObservable = of([1, 2, 3]);

  constructor()  

  ngOnInit(): void 
    this.myObservable.pipe(
      // here is some functions
    ).subscribe();
  


ngOnInit 运行后,observable 仍在运行和处理数据。数据到达后,管道更改模板。但这种变化发生在ngAfterViewInit 完成之后。所以我需要一个在管道之后运行的灵魂,并且渲染完成了正在发生的事情,因为管道完成了。

如何在我的 observable 和导致的渲染完成后运行代码(工具提示初始化)?

ngAfterViewChecked 不是一个好的解决方案,因为它总是在视图更改时运行,而且我的工具提示初始化也会更改视图。所以我只想运行一次这个初始化。

有什么解决办法吗?

【问题讨论】:

您在每次可观察到的更改后初始化您的工具提示? 在您依赖数据进行预加载的那一刻,您的整个代码将变为异步,因此请使用订阅处理异步数据。如果你想同步它,你可能想Resolve它 你看过rxjs的startWith操作符吗? @misha130 是的,因为当它发生变化时,视图也会发生变化,消除以前的工具提示装饰元素,我需要使用新的工具提示参数渲染新元素。 @AlekseySolovey 我使用异步数据并使用订阅,但在重新渲染视图后仍然无法运行工具提示初始化。 【参考方案1】:

我找到了解决方法:

我将所有代码放入与工具提示相关的单独组件中。实际上它是一个带有信息图标的label。在这个组件中,我将工具提示初始化代码放入ngAfterViewInit 函数中:

import  AfterViewInit, Component, Input  from '@angular/core';
import  TooltipService  from 'src/app/services/tooltip/tooltip.service';

@Component(
  selector: 'app-wizzard-label',
  templateUrl: './wizzard-label.component.html',
  styleUrls: ['./wizzard-label.component.scss'],
)
export class WizzardLabelComponent implements AfterViewInit 
  @Input() field: any = ;

  constructor(
    private tooltipService: TooltipService,
  )  

  ngAfterViewInit(): void 
    this.tooltipService.init();
  

现在当 observable 完成时,让我的微调器消失并显示这个组件。 ngAfterViewInit 做自己的工作,一切正常。

【讨论】:

【参考方案2】:

您可以使用 timout 函数作为解决方法,页面将在管道后加载并在一秒钟后执行您的代码,您可以将其减少到不到一秒钟,您可以通过尝试确定它:

export class MyComponent implements OnInit 
  myObservable = of([1, 2, 3]);
  constructor()  

  ngOnInit(): void 
    this.myObservable.pipe(
      setTimeout( ()=>
   // your code here
   , 1000)
    ).subscribe();
  


【讨论】:

setTimeout 不是一个好的解决方案,因为我们无法预测这个过程需要多长时间。也许 1 秒太少,也许太多。而且显然没有反应......【参考方案3】:

您可以使用async 管道轻松处理来自 Observables 的数据,如果您需要使用 RxJS pipe 函数,您可以将生成的 Observable 保存到一个新变量中,然后在其上使用 async 管道.

查看this stackblitz example

否则,如果管道中的副作用非常复杂,您可以使用 ChangeDetectorRef 手动触发 Angular 更改检测。 查看here 的文档。

【讨论】:

以上是关于在 Angular 11 中完成 Observable 和渲染后如何运行代码?的主要内容,如果未能解决你的问题,请参考以下文章

在 socket.io-client 中调用 IO 时出错,角度 8

量角器:失败:超时等待异步角度任务在11秒后完成

Angular js自动完成预先输入

for 循环在 Angular 中的 Observable 之前完成

Hammerjs 手势不适用于 Angular 版本 11?

自动完成材料 Angular 2 实施错误