【问题标题】:How to avoid using nested observables Angular 8如何避免使用嵌套的 observables Angular 8
【发布时间】:2020-03-25 17:38:40
【问题描述】:

我使用 typicode/json-server 创建了自己的 db.json 服务器,看起来像这样 -

 {
    "cart": [
        {
          "cartId": 1,
          "products": [
            { "pId": 1, "name": "aaa", "quantity":.. },
            { "pId": 2, "name": "bbb", "quantity":.. }
          ]
        },
        {
          "cartId": 2,
          "products": [{ "pId": 2, "name": "bbb", "quantity":.. }]
        }
      ]
}

这是将产品添加到购物车的方法:

addProductToCart((productObj:any)) {
    this.getCart() // uses POST, reference '/cart', returns observable
    .subscribe(cartId => {
      this.getProducts(cartId, productObj.pId) // uses GET, reference '/cart/cartId/pId', returns observable
      .subscribe(product => {
        // update properties of product here..
      });
    });
  }

我是 Angular 的新手,我知道嵌套的 observables 不是最佳实践。

如何避免使用嵌套的 observable?

有没有办法用不同的方法编写相同的方法?

【问题讨论】:

标签: angular observable angular8


【解决方案1】:

我建议研究 RxJS 提供的映射运算符。

3 种类型(我知道):switchMapconcatMapmergeMap

每个都将一个 observable 发射映射到另一个 observable,然后订阅并传播到外部订阅处理程序。

你现在可能会问,如果他们都做同样的事情,为什么会有 3 个不同的名字呢? 好吧,他们都做的有点不同。 ;)

首先 - switchMap:observables 是流,因此对于每个新的发射 switchMap,将其转换为另一个(内部)observable,但是当外部 observable 发射一个新值时,早期的内部订阅被取消,因此只有 1一次内部订阅是可能的。

mergeMap :顾名思义,它将所有内部可观察对象“合并”到流中,并在没有任何特殊顺序的情况下发出它们。

concatMap : 几乎像mergeMap 但它尊重顺序,因此外部流发出的项目也以相同的顺序从内部可观察对象发出。

什么时候用什么?
对于与顺序相关的流,您显然希望使用concatMap,如果您更看重吞吐量而不是顺序,请使用mergeMapswitchMap 最适合您“不关心”旧值的搜索和流,但要小心,因为 switchMap 取消内部 observables http 调用可能无法完成。

当然,在 RxJs 中还有很多东西可以发现(例如,resultSelectors 用于映射运算符)。这只是一个简短的概述。

延伸阅读:
https://medium.com/@luukgruijs/understanding-rxjs-map-mergemap-switchmap-and-concatmap-833fc1fb09ff
https://www.learnrxjs.io/operators/transformation/switchmap.html
https://www.learnrxjs.io/operators/transformation/mergemap.html
https://www.learnrxjs.io/operators/transformation/concatmap.html
RxJs 文档。 (他们有漂亮的大理石图)

现在举个例子:

addProductToCart(productObj: any) {
    this.getCart()
        .pipe(
            switchMap(cartId => this.getProducts(cartId, productObj.pId))
        )
        .subscribe(product => {
            // update properties of product here..
        });
}

我假设getCart() 发出购物车一次,我们无需担心取消内部订阅。如果假设成立,您也可以使用这些运算符中的任何其他运算符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2019-08-04
    • 2018-10-15
    • 2022-08-25
    • 1970-01-01
    • 2015-04-08
    相关资源
    最近更新 更多