在Angular服务中,我有以下方法:
// creates an Item and returns the ID of the created Item
createItem(item: Item): Observable<ItemId> {
return this.http.post<ItemId>('some_api_url', item);
}
// returns all Items
getAllItems(): Observable<Item[]> {
return this.http.get<Item[]>('some_api_url');
}
在我的模板中,我正在列表中显示项目。
我希望能够创建一个新项目,然后重新加载列表(以包括新创建的项目),所以我实现了以下内容:
this.itemService.createItem(item)
.pipe(
switchMap(createdId => this.itemService.getAllItems())
).subscribe(result => {
this.items = result;
});
这看似正常,但最后我还是要对createdId
做一些处理:
this.itemService.createItem(item)
.pipe(
switchMap(createdId => this.itemService.getAllItems())
).subscribe(result => {
this.items = result;
// i would like to use createdId here as well
});
所以我提出了以下建议:
this.itemService.createItem(item)
.pipe(
switchMap(createdId =>
combineLatest(this.itemService.getAllItems(), of(createdId)))
).subscribe(result => {
this.items = result[0];
// doing some stuff with result[1], which is the value of createdId
});
但是必须在combineLatest
内使用switchMap
并将createdId
明确地设为Observable
使我怀疑这是否是一个好的解决方案。
因此,基本上,我想创建并添加项目,更新列表(完成创建项目时),并在更新完成后使用已创建项目的ID。
有更好的方法吗?
我真的很感谢任何建议。
答案 0 :(得分:2)
深入研究RxJS运算符后,我发现最干净的解决方案可能是将concat
与toArray
组合在一起:
// import { concat } from 'rxjs';
// import { toArray } from 'rxjs/operators';
concat(
this.itemService.createItem(item),
this.itemService.getAllItems())
.pipe(toArray())
.subscribe((result: [ItemId, Item[]]) => {
// result[0] is the ItemId
// result[1] is the Item[]
});
答案 1 :(得分:1)
您可以使用concatMap
运算符。
尝试首先创建该项目,然后使用concatMap
运算符等待执行。在allItems
中观察执行结果,然后使用map
运算符合并结果。在订阅中,您将有一个对象createdItem
和allItems
const createdItem = this.itemService.createItem(item);
const allItems = this.itemService.getAllItems();
createdItem
.pipe(
concatMap(item =>
allItems.pipe(
map(items => ({
createdItem: item,
items
})
)
)
)
答案 2 :(得分:1)
您需要通过管道传递内部可观察的结果,以便进一步传递源发出的值。您可以按照以下步骤进行操作:
// I use a function here for the purpose of making the code more readable
const itemsWithNew = (newItemId) => this.itemService.getAllItems()
.pipe(map(items => ({items,newItemId})));
this.itemService.createItem(item)
.pipe(
switchMap(itemsWithNew)
).subscribe(({items, newItemId})=> {
this.items = items;
// newItemId is the new value
});
答案 3 :(得分:-1)
或者,switchmap
也接受第二个结果回调,用于一起处理外部值和内部值。
this.itemService.createItem(item).pipe(
switchMap(
() => this.itemService.getAllItems(),
(createdId, items) => {
// can do some stuff here with both outer and inner values
return { createdId, items };
},
),
).subscribe({ createdId, allItems }) => {
this.items = allItems;
});
答案 4 :(得分:-1)
// in your service
items: Item[]=[];
$$items=new BehaviorSubject(this.items);
// creates an Item and returns the ID of the created Item
createItem(item: Item): Observable<ItemId> {
return this.http.post<ItemId>('some_api_url', item)
}
// returns all Items
getAllItems(): Observable<Item[]> {
return this.http.get<Item[]>('some_api_url').pipe(map(response=>{
return {//format response here//}
}).subscribe(result=>{
this.items=result;
this.$$items.next(this.items);
})
}
returnItemsAsObs(){
return this.$$items.asObservable();
}
//in your component
items:Item[]
$$items: Subscription
ngOninit(){
this.service.getAllItems()
this.$items=this.service.returnItemsAsObs().subscribe(items=>{
this.items=items;
return this.items;
})
onCreateItem(item){
return this.service.createItem(item).subscribe(item=>{
if(item.length<0){
//call other service for itemid manipulation
this.service.getAllItems();
}
})
}
}