我有一个问题,我的异步管道正在触发 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();
}
您提供的代码可以正常工作,但它远非最佳,也不是您所期望的。有什么问题:
// 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
您似乎正在尝试将新结果附加到已有的结果中
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 });
}