如何从 Observable<Array<any>> 中删除特定元素
Posted
技术标签:
【中文标题】如何从 Observable<Array<any>> 中删除特定元素【英文标题】:How to remove specific element from Observable<Array<any>> 【发布时间】:2016-11-06 00:32:53 【问题描述】:有一个地点数组的 Observable:
places: Observable<Array<any>>;
在模板中它与异步管道一起使用:
<tr *ngFor="let place of places | async">
...
</tr>
在一些用户操作之后,我需要从这个数组中删除具有特定 id 的地方。我的代码中有这样的东西,但它不起作用:
deletePlace(placeId: number): void
this.apiService.deletePlace(placeId)
.subscribe(
(res: any) =>
this.places
.flatMap((places) => places)
.filter((place) => place.id != placeId);
,
(err: any) => console.log(err)
);
你能帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:你不能这样做,因为你不能“更新”一个 observable(即它不保持状态),但你可以通过它对事件做出反应。
对于您的用例,我将利用 scan
运算符并将两个流合并为一个:
这是一个示例:
let obs = this.http.get('/data').map(res => res.json());
this.deleteSubject = new Subject();
this.mergedObs = obs.merge(this.deleteSubject)
.startWith([])
.scan((acc, val) =>
if (val.op && val.op==='delete')
var index = acc.findIndex((elt) => elt.id === val.id);
acc.splice(index, 1);
return acc;
else
return acc.concat(val);
);
要触发元素删除,只需在主题上发送一个事件:
this.deleteSubject.next(op:'delete', id: '1');
看到这个 plunkr:https://plnkr.co/edit/8bYoyDiwM8pM74BYe8SI?p=preview。
【讨论】:
很想看到这个问题的更新答案,已经尝试了一天多。【参考方案2】:您可以利用 filter 运算符:
this.places$
.pipe(
map(places =>
// Here goes some condition, apply it to your use case, the condition only will return when condition matches
return places.filter(place => place.placeId !== 0);
),
map(response => (this.users$ = of(response)))
)
.subscribe(result => console.warn('Result: ', result));
【讨论】:
@kushalBaldev,不管模板更新,这都会返回一个 Observable;如果您的模板中有绑定,这将自动更新,因为您的可观察对象和模板之间存在同步。【参考方案3】:过滤函数是不可变的,不会改变原始数组。
我会将 deletePlace 函数更改为如下所示:-
deletePlace(placeId: number): void
this.apiService.deletePlace(placeId)
.subscribe(
(res: any) =>
this.places = this.places.filter((place) => place.id != placeId);
,
(err: any) => console.log(err)
);
【讨论】:
【参考方案4】:RxJS 版本 6
将接受的答案与 RxJS 6 和 typescript
一起使用会引发错误,因为 observables
持有不同的类型。你最好使用combineLatest
,你也可以使用zip
,但它不起作用!你刚才问为什么?答案是here :)
combineLatest([
this.items$,
this.deleteItem$
]).pipe(
takeUntil(this.onDestroy),
tap(([items, deleteItem]) =>
if (deleteItem && deleteItem.op === 'deleteItem')
var index = items.findIndex((item) => item.id === deleteItem.id);
if (index >= 0)
items.splice(index, 1);
return items;
else
return items.concat(deleteItem);
)
).subscribe();
然后你可以发送事件..
this.deleteItem$.next( op: 'deleteItem', id: '5e88fce485905976daa27b8b' );
我希望它会帮助某人..
【讨论】:
这个解决方案的问题是,combineLatest 也总是发出最新的 deleteItem$ 值。意思是,在 deleteItem$ 第一次发出后,脚本会在每次发出 items$ 时尝试删除这个项目。以上是关于如何从 Observable<Array<any>> 中删除特定元素的主要内容,如果未能解决你的问题,请参考以下文章