首页 > 解决方案 > 导致 ExpressionChangedAfterItHasBeenChecked 的 Observables

问题描述

我有一个选择框,它将使用 *ngFor 和异步管道填充。

<select (change)="onChange($event)">
    <option *ngFor="let ccy of availableCCYs$ | async" [value]="ccy.name" [selected]="ccy.name == selectedCCY">{{ccy.name}}
    </option>
</select>

我希望根据另一个 Observable Coin$ 中的值更新 availableCCYs$ observable。我有一个包含要使用的 ccys 的变量。

ccys = [
    {
      id: 1,
      name: "GBP",
    },
    {
      id: 2,
      name: "USD"
    }
  ]

我有另一个 Observable,它创建了一个硬币列表,当它这样做时,我正在为选择框设置 availableCCYs$

this.coinsByCCY$ = this.coins$.pipe(
      map(coin => {
        if (coin.filter(GBPCoin => GBPCoin.ticker.includes('GBP')).length === 0) {
          let ccysNoGBP = this.ccys.filter(ccy => ccy.name == "USD")
          this.availableCCYs$ = of(ccysNoGBP)
          return coin.filter(USDCoin => USDCoin.ticker.includes('USD'))
        } else {
          this.availableCCYs$ = of(this.ccys)
          return coin.filter(GBPCoin =>   GBPCoin.ticker.includes('GBP'))
        }
      }),
    )

我仍然在使用 RxJs 和使用异步管道,当我运行代码时,我得到 ExpressionChangedAfterItHasBeenCheckedError。如果没有带有 GBP 的硬币,则从选择中的选项中删除 GBP。总是有美元的硬币。

如何根据 CoinsByCCY$ Observable 是否包含 GBP 或 USD 反应性地设置选择框中的选项

标签: angularrxjs

解决方案


如果您想让它更具反应性,那么您可以扩展coinsByCCY$并执行以下操作:

this.coinsByCCY$ = this.coins$.pipe(
      map(coin => {
        if (coin.filter(GBPCoin => GBPCoin.ticker.includes('GBP')).length === 0) {
          return coin.filter(USDCoin => USDCoin.ticker.includes('USD'))
        } else {
          return coin.filter(GBPCoin => GBPCoin.ticker.includes('GBP'))
        }
      }),
    );

this.availableCCYs$ = this.coinsByCCY$.pipe(
     map((coinsByCCY)=> {
       if(coinsByCCY.find((USDCoin)=> USDCoin.ticker.includes('USD'))) { // check if it's USD
         return this.ccys;
       } else {
         return this.ccys.filter(ccy => ccy.name == "USD");
       }
     })
)

否则,如果您在 observable 中执行类似操作this.availableCCYs$ = of(ccysNoGBP),则会产生副作用;在这种情况下,您应该使用tap运算符。


推荐阅读