【问题标题】:Angular - edit a BehaviorSubject ArrayAngular - 编辑 BehaviorSubject 数组
【发布时间】:2021-11-29 14:00:23
【问题描述】:

我正在向服务器发送修改其中一个用户的请求。

作为响应,服务器发回更新的用户。

之后我尝试像这样更新所有用户的 BehaviorSubject:

   private currentHeroes = new BehaviorSubject<Hero[]>(null);
   currentHeroes$ = this.currentHeroes.asObservable();


 powerUp(id: number) {
return this.http
  .post<Hero>(environment.apiUrl + 'heroes/powerUp/' + id, {})
  .pipe(
    tap((updatedHero: Hero) => {
      this.currentHeroes.next(
        this.currentHeroes.value.map((hero: Hero) =>
          hero.id === updatedHero.id ? updatedHero : hero
        ).sort(a=>a.currentPower)
      );
    })
  );

}

删除时:

    delete(id: number) {
return this.http.delete<Hero>(environment.apiUrl + 'heroes/' + id).pipe(
  tap((deletedHero: Hero) => {
    this.currentHeroes.value.filter(
      (hero: Hero) => hero.id !== deletedHero.id
    );
  })
);

}

我正在尝试修改用户数组。用更新的用户替换旧用户。

而且代码没有到达 currentHeroes$ 的管道。 我不确定为什么会发生这种情况,或者我该如何解决。

我尝试从管道返回一个值或使用 tap 而不是 map 但没有运气。

有没有人可以看看向我解释为什么会发生这种情况?或者我该如何解决?

谢谢!

【问题讨论】:

    标签: angular rxjs behaviorsubject


    【解决方案1】:

    更新数组中的对象

    变体 1:使用 value 的吸气剂 BehaviorSubject

    您不必将pipe 转至BehaviorSubject。您只需要在源 observable(HTTP 请求)上使用 tap 运算符并在其回调中更新 BehaviorSubjecttap 运算符类似于map,但不会转换传入的排放。因此,它非常适合执行更新局部变量等副作用。

    import { tap } from 'rxjs/operators';
    
    powerUp(id: number) {
      return this.http.post<Hero>(environment.apiUrl + 'heroes/powerUp/' + id, {}).pipe(
        tap((updatedHero: any) => {
            this.currentHeroes.next(
              this.currenHeroes.value.map((hero: Hero) =>        // <-- `Array#map` function
                hero.id === updatedHero.id ? updatedHero : hero
              )
            );
          }
        })
      );
    }
    

    变体 2:使用 withLatestFrom 运算符

    如果您不想使用来自BehaviorSubjectvalue getter,您可以尝试使用withLatestFrom 运算符来获取它的最新值。

    import { tap, withLatestFrom } from 'rxjs/operators';
    
    powerUp(id: number) {
      return this.http.post<Hero>(environment.apiUrl + 'heroes/powerUp/' + id, {}).pipe(
        withLatestFrom(this.currentHeroes$),
        tap(([updatedHero, currentHeroes]) => {
            this.currentHeroes.next(
              currenHeroes.map((hero: Hero) => 
                hero.id === updatedHero.id ? updatedHero : hero
              )
            );
          }
        })
      );
    }
    

    删除数组中的对象

    如 cmets 中所述,要删除数组中的元素,您可以使用 Array#filter 而不是 Array#map 函数。

    变体 1:使用 value 的吸气剂 BehaviorSubject

    import { tap, withLatestFrom } from 'rxjs/operators';
    
    powerUp(id: number) {
      return this.http.delete<Hero>(environment.apiUrl + 'heroes/' + id).pipe(
        tap(([deletedHero, currentHeroes]) => {
            this.currentHeroes.next(
              this.currentHeroes.value.filter((hero: Hero) => hero.id !== deletedHero.id)
            );
          }
        })
      );
    }
    

    变体 2:使用 withLatestFrom 运算符

    import { tap, withLatestFrom } from 'rxjs/operators';
    
    powerUp(id: number) {
      return this.http.delete<Hero>(environment.apiUrl + 'heroes/' + id).pipe(
        withLatestFrom(this.currentHeroes$),
        tap(([deletedHero, currentHeroes]) => {
            this.currentHeroes.next(
              currentHeroes.filter((hero: Hero) => hero.id !== deletedHero.id)
            );
          }
        })
      );
    }
    

    【讨论】:

    • 但实际上我还有一个问题。多亏了你,我明白了我的错误!但是在删除英雄的情况下。 ----> hero.id === 已删除Hero.id ? {} : 英雄;不起作用。我错过了什么吗?因为只是 {} 并没有像我想象的那样工作
    • 我已经编辑了我的问题,所以你可以看看我怎样才能尝试删除一个英雄
    • 不,在这种情况下,数组中有一个空对象。要删除对象,您可以使用 Array#filter: currenHeroes.filter((hero: Hero) =&gt; hero.id !== deletedHero.id)
    • 不幸的是,我试过了,它说:“BehaviorSubject'.ts(2339) 类型上不存在属性“过滤器”
    • 是的,因为这是答案的第二个变体。为此,您需要使用 withLatestFrom 运算符。或者你可以只使用value getter:this.currentHeroes.value.filter((hero: Hero) =&gt; hero.id !== deletedHero.id)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    相关资源
    最近更新 更多