Angular - 编辑一个数组类型的主题

Angular - Edit a Subject which is a type of Array

我正在编写一个应用程序,管理员可以在其中升级用户的权限。

在我向服务器发送请求以增加用户的权力之后。我从服务器返回用户列表:

powerUp(id: number) {
return this.http
  .post<Hero[]>(environment.apiUrl + 'heroes/powerUp/' + id, {})
  .pipe(
    map((heroes) => {
      this.currentHeroes.next(hero);
    })
  );

}

这里是主题:

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

问题是它不是主事,因为我可以从服务器 return 只有正在启动的特定用户。

powerUp(id: number) {
    return this.http
      .post<Hero[]>(environment.apiUrl + 'heroes/powerUp/' + id, {})
      .pipe(
        map((hero) => {
          // update the particular hero in the currentHeroes subject
        })
      );
  }

我的问题是如何在不从服务器返回整个列表的情况下修改 currentHeroes 主题(仅更新的用户)without.next()。

我试过以下:

  powerUp(id: number) {
    return this.http
      .post<Hero>(environment.apiUrl + 'heroes/powerUp/' + id, {})
      .pipe(
        map((updatedHero) => {
          this.currentHeroes$.pipe(
                // doesn't enter here
                map((oldHeroes) => {
                  const index = oldHeroes.findIndex((hero) => hero.id === id);
                  oldHeroes[index] = updatedHero;
                })
              );
            })
          );
      }

英雄卡模板

export class HeroCardComponent implements OnInit {
  @Input() hero: Hero;

  constructor(public heroService: HeroService, private toastr: ToastrService) {}

  ngOnInit(): void {}

  powerUp(id: number, name: string) {
    this.heroService.powerUp(id).subscribe(() => {
      this.toastr.success(`${name} was successfully powered up!`);
    });
  }

  delete(id: number, name: string) {
    this.heroService.delete(id).subscribe(() => {
      this.toastr.success(`${name} was successfully deleted`);
    });
  }
}

有人可以解释一下我该怎么做吗?

您可以替换之前的 currentHeroes$,如果您使用的是 async 管道,它应该开箱即用。

如果您的模板如下所示:

<div *ngFor="let hero of (currentHeroes$ | async)">
  <app-hero-card [hero]="hero"></app-hero-card>
</div>

您的组件可能如下所示:

@Component({…})
export class HeroListComponent {

  currentHeroes$: Observable<Hero[]>
  constructor(private heroService: HeroService) {
    this.currentHeroes$ = this.heroService.getHeroes()
  }

  powerUp(heroId: string) {
    this.currentHeroes$ = this.heroService.powerUp(heroId).pipe(
      switchMap(updatedHero => {
          return this.currentHeroes$.pipe(
            map(oldHeroes => {
               const index = oldHeroes.findIndex(hero => hero.id === updatedHero.id)
               oldHeroes[index]=updatedHero
               return oldHeroes
            })
          );
      })
     );
  }
}

现在对魔术进行一些解释:

  1. HeroService.powerUp(heroId) 将 return 我们一个 observable,一旦网络请求完成,它将发出更新的英雄
  2. 然后我们通过应用来自 RxJS 的 switchMap 管道来转换可观察对象。 switchMap 所做的是它允许说;好的,无论这里发生什么,它都将由另一个可观察对象(我们 return)
  3. 处理
  4. 在 returned Observable 上,我们只是获取旧的 currentHeroes$ observable 并通过查找它的 id 并更新数组项来替换旧的英雄。最后 return 更新数组

小费

如果后端 return 更新了列表或者您可以触发重新获取,代码会少很多

如果后端return是完整列表

powerUp(heroId:string) {
  this.currentHeroes$ = this.heroService.powerUp(heroId)
}

如果要触发重新获取

powerUp(heroId:string) {
  this.currentHeroes$ = this.heroService.powerUp(heroId).pipe(
    switchMap(_updatedHero => this.heroService.getHeroes())
  );

}