typescript 如何从 Observable<Array<any>> 中删除特定元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38181954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:37:12  来源:igfitidea点击:

How to remove specific element from Observable<Array<any>>

javascripttypescriptangularrxjs

提问by daslashi

There is an Observable of the array of places:

有一个位置数组的 Observable:

places: Observable<Array<any>>;

In template it used with the async pipe:

在模板中,它与异步管道一起使用:

<tr *ngFor="let place of places | async">
  ...
</tr>

After some user actions I need to remove the place with specific id from this array. I have something like this in my code, but it doesn't work:

在一些用户操作之后,我需要从这个数组中删除具有特定 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)
  );    
}  

Can you help me with this?

你能帮我解决这个问题吗?

回答by Thierry Templier

You can't do it this way since you can't "update" an observable (i.e. it doesn't keep states) but you can react to an event through it.

你不能这样做,因为你不能“更新”一个可观察的(即它不保持状态),但你可以通过它对事件做出反应。

For your use case, I would leverage the scanoperator and merge two streams into a single one:

对于您的用例,我将利用scan运算符并将两个流合并为一个:

  • one for the initial loading
  • another one for the delete event.
  • 一个用于初始加载
  • 另一个用于删除事件。

Here is a sample:

这是一个示例:

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);
  }
});

To trigger an element deletion, simply send an event on the subject:

要触发元素删除,只需在主题上发送一个事件:

this.deleteSubject.next({op:'delete', id: '1'});

See this plunkr: https://plnkr.co/edit/8bYoyDiwM8pM74BYe8SI?p=preview.

请参阅此 plunkr:https://plnkr.co/edit/8bYoyDiwM8pM74BYe8SI ?p =preview 。

回答by Krishnanunni Jeevan

The filter function is immutable and won't change the original array.

filter 函数是不可变的,不会改变原始数组。

I would change the deletePlace function to something like this:-

我会将 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)
  );    
}  

回答by Tecayehuatl

You can take advantage of filteroperator:

您可以利用过滤器运算符:

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));

回答by user12163165

RxJS version 6

RxJS 版本 6

Using the accepted answer with RxJS 6and typescriptwill throw an error because the observableshold different types. you better use combineLatest, you could also use zipbut it will not work! did you just ask why? the answer is here:)

将接受的答案与RxJS 6一起使用,并且typescript会因为observables持有不同的类型而引发错误。你最好用combineLatest,你也可以用,zip但是不行!你刚才问为什么?答案在这里:)

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();

then you can send the event..

然后你可以发送事件..

this.deleteItem$.next({ op: 'deleteItem', id: '5e88fce485905976daa27b8b' });

I hope it will help someone..

我希望它会帮助某人..