异步管道在 POST 请求后触发

问题描述 投票:0回答:2

我有一个问题,我的异步管道正在触发 GET 请求,但我只想触发一个 post 请求并将新元素放入数组中。我的函数如下所示:

  create(hersteller: Hersteller) {
    this.herstellerService.create(hersteller).subscribe((neuerHersteller) => {
      this.hersteller$ = this.hersteller$.pipe(
        map((hersteller) => [neuerHersteller, ...hersteller])
      );
    });
  }

在我的 html 模板中,我有 asnyc 管道:

...
[tableData]="(hersteller$ | async) ?? []"
...

行为如下:首先发送POST请求。之后,触发 GET 请求,我收到所有元素,包括新元素。然后,我复制新元素,导致它在数组中出现两次。

不复制新元素。比它在数组中只出现一次,但 GET 请求仍在触发并重新加载表。

编辑 init hersteller$:

  hersteller$: Observable<Hersteller[]>;

  constructor(
    private herstellerService: HerstellerService,
    private dialog: MatDialog
  ) {
    this.hersteller$ = this.herstellerService.readAll();
  }
angular rxjs
2个回答
0
投票

您提供的代码可以正常工作,但它远非最佳,也不是您所期望的。有什么问题:

// You are initializing Observable with service call
// Async pipe will subscribe to it and handle the result
// That's OK
this.hersteller$ = this.herstellerService.readAll();

// But here, you are re-assigning it, now with pipe and mapping
// Async pipes unsubscribes the previous one an subscribe to new one
// This triggers the GET
this.hersteller$ = this.hersteller$.pipe(
  map((hersteller) => [neuerHersteller, ...hersteller])
);

在您的情况下,您可以将

hersteller
更改为同步属性,手动订阅,从而删除
async
管道。

hersteller: Hersteller = [];

constructor(
  private herstellerService: HerstellerService,
  private dialog: MatDialog
) {
  this.herstellerService.readAll().subscribe((hersteller) => {
    this.hersteller = hersteller;
  });
}

create(hersteller: Hersteller) {
  this.herstellerService.create(hersteller).subscribe((neuerHersteller) => {
    this.hersteller = [...this.hersteller, neuerHersteller];
    // Or maybe just with push, if neuerHersteller is not an Array
    // this.hersteller.push(neuerHersteller);
  });
}
// And in template
/*
...
[tableData]="hersteller"
...
*/

坚持使用异步属性是可能的,但在我看来过于复杂。

// BehaviorSubject gives you an access to its value
hersteller$: BehaviorSubject<Hersteller> = new BehaviorSubject<Hersteller>([]);

constructor(
  private herstellerService: HerstellerService,
  private dialog: MatDialog
) {
  this.herstellerService.readAll().subscribe((hersteller) => {
    // This is ugly, but doable
    this.hersteller$.next(hersteller);
  });
}

create(hersteller: Hersteller) {
  this.herstellerService.create(hersteller)
    .pipe(
      // Merge new value with hersteller current value
      map((neuerHersteller) => [...this.hersteller$.value, neuerHersteller])
    )
    .subscribe((neuerHersteller) => {
      this.hersteller$.next(neuerHersteller);
  });
}
// Template stays the same

0
投票

您似乎正在尝试将新结果附加到已有的结果中

Observable

您不应该重新分配可观察值,但应该使用

Subject
发出数组的所有新元素,并且可以使用
scan
将它们放入数组中。

这是该模式的示例
让我们来分解一下:

  • itemsSubj
    发出新的
    Item
    ,允许您将新的
    Item
    添加到数组
  • items$
    对每个
    itemsSubj
    发射作出反应,通过
    Item 运算符
     将发射的 
    scan
  • 添加到其数组(最初为空)
  • factory
    模拟您的服务调用返回
    Observable<Item>
  • create
    获取
    Observable<Item>
    并告诉
    itemsSubj
    发出它。
  itemsSubj = new Subject<Item>();
  items$ = this.itemsSubj.pipe(
    scan((acc: Item[], newItem: Item) => [...acc, newItem], [])
  );

  create() {
    this.factory().subscribe(item => this.itemsSubj.next(item))
  }

  factory() {
    this.itemNum++;
    return of({ num: this.itemNum });
  }
© www.soinside.com 2019 - 2024. All rights reserved.