【问题标题】:Angular subscribe to change of variable in another componentAngular订阅另一个组件中的变量更改
【发布时间】:2021-11-25 13:28:18
【问题描述】:

我有一个包含 3 个组件和 1 个服务的应用程序:

  • 应用程序组件。这包含我的导航栏等。在导航栏中有一个垫选择,您可以在其中选择客户。
  • orders.component。列出当前选定客户的订单。
  • products.component。列出当前选定客户的产品。
  • 客户服务。一些用于客户的函数,也是与当前选择的客户相关的变量

所需状态:

  • 当未选择客户且用户导航至订单或产品时,不应调用 API。
  • 当用户在订单/产品页面上时在导航栏中选择客户时,API 应触发以获取所选客户的订单/产品。
  • 客户变更时,应触发 API 加载新客户订单/产品
  • 当客户被选中并且用户导航到订单/产品时,应该直接调用 API 来获取数据

当前状态

  • 目前我已将customerObserver: Subject<boolean> = new Subject<boolean>(); 添加到customer.service。
  • 在导航栏(app.components)中选择客户时,它会调用customer.service中的一个函数,该函数最终将执行this.customerObserver.next(this.customer);
  • 在订单和产品组件中,我都这样做:
  ngOnInit(): void {
    if (this.customerService.customer) {
      this.loadOrders();
    }

    this.customerService.customerObserver.subscribe(customer => {
      if(customer) {
        this.loadOrders();
      }
    });
  }

该功能运行良好,但我意识到,由于我从不取消订阅,这完全搞砸了应用程序,因为它在导航时会创建大量订阅。我在订单中添加了取消订阅(请参阅下面的 sn-p),但是当我四处导航时,我收到以下错误:ObjectUnsubscribedErrorImpl {message: 'object unsubscribed', name: 'ObjectUnsubscribedError'}

  ngOnDestroy() {
    this.customerService.customerObserver.unsubscribe();
  }

我已经尝试阅读订阅了一段时间,但卡住了如何继续。关于如何安排以达到所需状态的任何提示?

【问题讨论】:

    标签: angular rxjs subscribe


    【解决方案1】:

    您可以从服务向组件观察者发送数据。

    private customerSubject = new Subject<number>();
    customerSelectedAction$ = this.customerSubject.asObservable();
    
    products$ = this.customerSelectedAction$.pipe(
     switchMap(customerId=>this.http.get<Product[]>(`${this.url}?customerId=${customerId}`))
        .pipe(
          tap(data => console.log(data)),
          catchError(this.handleError)
      ));
    
    orders$ = this.customerSelectedAction$.pipe(
     switchMap(customerId=>this.http.get<Orders[]>(`${this.url}?customerId=${customerId}`))
        .pipe(
          tap(data => console.log(data)),
          catchError(this.handleError)
      ));
    
    selectedCustomerChanged(customer: Customer): void {
      this.customerSubject.next(customer.id);
    }
    

    之后,您订阅 products$orders$ observables,具体取决于您是哪个组件。并使用导航栏中的selectedCustomerChanged(customer: Customer) 方法。

    【讨论】:

    • 所以如果我理解正确的话,我会把上面的所有代码放在customer.service中吗?
    • 是的,在CustomerService
    【解决方案2】:

    您可以在订阅数组中的每个组件中管理订阅,您可以在此处查找最佳答案: Unsubscribing an array of subscriptions

    另一个提示,您可以使用以 null 开头的私有 BehaviorSubject(和公共 asObservable 道具),因此您可以完全删除 customerObserver: Subject&lt;boolean&gt; = new Subject&lt;boolean&gt;();。 如果客户不为空,您只需订阅该 observable 并加载订单(您也可以使用 distinct 直到更改)。

    【讨论】:

    • 嗨!我将检查是否有订阅数组的选项。对于您发布的第二个选项。例如,如果我希望在订单页面中更改客户时让 orders.component 重新加载订单,这将如何适应?
    • 由于您订阅了 流并在客户更改上执行下一步 - 您可以像在示例中那样重新加载订单。实际上有很多方法可以做到这一点 - 如果你想要更多的分离,订单组件实际上可以订阅一个订单服务(或者更好的是,一个专门用于视图的外观),它将对客户的变化做出反应
    猜你喜欢
    • 2020-07-17
    • 2017-10-13
    • 2016-06-14
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2018-03-15
    • 1970-01-01
    相关资源
    最近更新 更多