【问题标题】:Angular observable receives data only once onInitAngular observable 仅在 onInit 时接收一次数据
【发布时间】:2022-11-30 05:16:48
【问题描述】:

我正在通过 Moshs 的 Angular 类构建一个简单的购物页面。由于本教程已经很老了,所以我不得不逐步完成引导程序和角度的更改,并且在进入购物车部分之前我做得很好。

我在这里遇到的问题是,我使用的是 mysql 数据库而不是 firebase,我计算购物车中商品总数的实现没有按预期工作,但我不知道为什么。

所以我正在做的是:在我的产品页面上,您可以在购物车中添加/删除商品——数据被发送到服务器,之后我通过一个可观察到的发布请求返回更新后的购物车,如下所示:

getCartContent(): Observable<ShoppingCart> {
  return this.getOrCreateCart().pipe(
      switchMap(cart => {
        return this.http.post<ShoppingCart>(this.url + 'cart_api.php', JSON.stringify(
          [
            'getCartContent',
            {
              cartId: cart
            },
            ''
          ]
        ));
      })
    );
  }

我在这里使用 switchmap,因为我必须先获取 cartId,然后再获取相应的购物车商品。 这工作正常,我在产品页面上更新了购物车数据,并将新购物车数据写入本地存储/控制台,显示数据已按预期返回。

我现在尝试做的是在导航栏中显示购物车中的商品总数。因此,我也在 navbar.ts 中订阅了这个可观察对象,并希望在每次执行 getCartContent() 时重新计算金额。

我在导航栏中的代码如下所示:

  ngOnInit() {
    this.ShoppingCartService.getCartContent().subscribe(cart => {
        console.log(cart); // just to see, if this subscription receives data
        this.shoppingCartItemsCount = 0;
        for (let productId in cart.ITEMS) {
          this.shoppingCartItemsCount += Number(cart.ITEMS[productId]);
        }
      }
    );
  }

结果是,购物车数据已正确记录在控制台中 - 但仅在我加载页面时记录一次 - 购物车中商品的任何更改都不会反映在导航栏订阅中,而是会在产品页面中显示。

我很确定我的想法是错误的,但我完全被困住了——非常感谢任何帮助。

【问题讨论】:

    标签: angular http post observable subscription


    【解决方案1】:

    我理解您的困惑,实际上,即使 getCartContent 返回一个可观察对象,它也只被调用一次。您需要的是服务类中的 BehaviourSubject 来反映更改。以下是如何实现它的常见做法。

    private cartContent$: BehaviourSubject<ShoppingCart> = new BehaviourSubject();
    public listenToCartChanges(): Observable<ShoppingCart> {
      return this.cartContent$.asObservable();
    }
    

    为了将更改推送到主题,您可以在您的函数上添加 tap 以将更改推送到 BehaviourSubject。

       getCartContent(): Observable<ShoppingCart> {
      return this.getOrCreateCart().pipe(
          switchMap(cart => {
            return this.http.post<ShoppingCart>(this.url + 'cart_api.php', JSON.stringify(
              [
                'getCartContent',
                {
                  cartId: cart
                },
                ''
              ]
            ));
          }),
          pipe(res => {
            this.cartContent$.next(res)
          }
        );
      }
    

    最后,您需要在导航组件中订阅函数listenToCartChanges()(不要忘记在ngOnDestroy 上取消订阅以防止内存泄漏)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-16
      • 1970-01-01
      • 2016-04-12
      • 2019-12-25
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2022-11-12
      相关资源
      最近更新 更多