在哪里订阅 Angular 中的 observable、构造函数或 ngoninit [关闭]

Posted

技术标签:

【中文标题】在哪里订阅 Angular 中的 observable、构造函数或 ngoninit [关闭]【英文标题】:Where to subscribe to an observable, constructor or ngoninit in Angular [closed] 【发布时间】:2021-01-25 13:35:19 【问题描述】:

我知道这是在 SO 和互联网上发布的,但我正在阅读很多不同的东西,我现在只是有点困惑。

2 个问题 -

    订阅我的组件、constructor() 或 NgOnInit() 的最佳位置在哪里? 在订阅 Observable 时我应该使用管道以便 Angular 可以销毁它还是我不必使用 ngondestroy?有点疑惑为什么订阅后还有管道?

这是我的一项服务的示例,在我的导航栏组件中,我订阅了侦听来自服务的窗口大小变化。

在我的构造函数中,我有这个 -

this.responsiveService.getMobileStatus()
  .subscribe(mobileStatus => 
    this.isMobile = mobileStatus.status;
    if (mobileStatus.width < 568) 
      this.inputPlaceholder = this.placeholderWithSearch;
     else 
      this.inputPlaceholder = this.placeholderWithoutSearch;
    
  );

【问题讨论】:

【参考方案1】:

我会说最好使用async 管道并让角度处理取消订阅。它产生更清晰的代码;

让我们考虑在构造函数中订阅的代码

export class MyClassComponent implements OnInit, OnDestroy 
  sub: any;
  componentName: any;
  constructor(private navbarService: NavbarService) 
  
  ngOnInit() 
    this.sub = this.navbarService.getComponentNameObv()
    .subscribe(componentName => 
      this.componentName = componentName;
    );
  
  ngOnDestroy() 
    this.sub.unsubscribe()
  


使用async 管道我们可以重构

export class MyClassComponent 
  componentName$ = this.navbarService.getComponentNameObv();
  mobileStatus$ = this.responsiveService.getMobileStatus().pipe(
    tap(mobileStatus => 
      this.isMobile = mobileStatus.status;
      if (mobileStatus.width < 568) 
        this.inputPlaceholder = this.placeholderWithSearch;
       else 
        this.inputPlaceholder = this.placeholderWithoutSearch;
      
    )
  )
  constructor(private navbarService: NavbarService) 
  

代码更短,也更容易测试

【讨论】:

如果我收到后必须做一点逻辑怎么办?而不是像我的例子那样只设置 1 个值,我必须设置几个值并做一些逻辑。那么应该在构造函数中还是在ngoninit中? 然后您将通过管道传输 observable 并根据您想要的结果,您可以使用 rxjs 运算符来转换数据或将数据用于特定目的,任何特定场景? 你让我编辑我的 OP 以显示一点逻辑。 好的,我用一个不同的示例编辑了我的 OP,显示了当我订阅服务侦听窗口调整大小事件时运行的一些逻辑。 我添加了一个点击操作符来接入可观察的流【参考方案2】:

    使用ngOnInit 订阅是个好习惯,因为@Input 绑定直到这个生命周期钩子才被初始化,所以它们在构造函数中还没有准备好,并且通常可观察对象可以依赖这些值。即使他们不这样做,保持一致并始终在同一个地方只是一个很好的做法。

    您应尽可能使用async 管道以避免手动订阅管理,但这并不总是可行或合理的。

【讨论】:

谢谢!很高兴知道。 你能解释一下我什么时候应该和不应该使用异步管道吗? 就像我说的,只要可行。如果你只是想在模板中使用一个值,那么你可能应该使用异步管道。但是如果你在其他非模板地方需要那个值,或者需要根据这个值产生其他效果,那么异步管道可能就不实用了。

以上是关于在哪里订阅 Angular 中的 observable、构造函数或 ngoninit [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

取消订阅服务内部的 Observables?

在 angular2 中的 ngOnInit 之后,在构造函数中订阅服务

我应该取消订阅根 Angular 组件中的 observables 吗?

我们是不是需要取消订阅 Angular 中的 http 调用? [复制]

Rx 操作符三

如何在 Angular 中查看数据中的字段(订阅)