Subject和Observable,如何删除item,filter()列表和next()

时间:2018-03-20 13:25:12

标签: angular rxjs observable rxjs5 subject-observer

我有一个使用Subject和Observable设置的歌曲列表(在视图中显示为| async),现在我想从列表中删除一首歌,执行一些filter()并调用{{1在主题上。

我如何以及在何处过滤?现在我正在对主题进行next()并将其传递给getValue(),以及主题。这似乎是错误的和循环的。

我也尝试订阅主题并以这种方式获取数据,过滤它并在next()内调用next(),但我得到了一个RangeError。

我可以通过存储所有已删除的ID来过滤Observable。然后,通过在那里删除歌曲,主题的列表变得不同步,并且每个观察者都必须具有看似荒谬的已删除id的列表。我的老人和精神都快速增长。请帮我上网:(

subscribe()

3 个答案:

答案 0 :(得分:0)

如果您想将所有内容保存在流中,那么您可以从Redux剧本中获取一个页面并执行以下操作:



const actions = new Rx.Subject();

const ActionType = {
  SET: '[Song] SET',
  DELETE: '[Song] DELETE'
};

const songs = [
  { id: 1, name: 'First' },
  { id: 2, name: 'Second' },
  { id: 3, name: 'Third' },
  { id: 4, name: 'Fourth' },
  { id: 5, name: 'Fifth' }
];

actions
.do(x => { console.log(x.type, x.payload); })
.scan((state, action) => {
  switch(action.type) {
    case ActionType.SET:
    	return action.payload;
    case ActionType.DELETE:
      return state.filter(x => x.id !== action.payload);
  }
  return state;
}, [])
.subscribe(x => { console.log('State:', x); });


window.setTimeout(() => {
  actions.next({ type: ActionType.SET, payload: songs });
}, 1000);

window.setTimeout(() => {
  actions.next({ type: ActionType.DELETE, payload: 2 });
}, 2000);

window.setTimeout(() => {
  actions.next({ type: ActionType.DELETE, payload: 5 });
}, 3000);

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.7/Rx.min.js"></script>
&#13;
&#13;
&#13;

或类似的东西:

&#13;
&#13;
const deletes = new Rx.Subject();

const songs = Rx.Observable.of([
  { id: 1, name: 'First' },
  { id: 2, name: 'Second' },
  { id: 3, name: 'Third' },
  { id: 4, name: 'Fourth' },
  { id: 5, name: 'Fifth' }
]);

window.setTimeout(() => {
  deletes.next(2);
}, 1000);

window.setTimeout(() => {
  deletes.next(5);
}, 2000);

songs.switchMap(state => {
  return deletes.scan((state, id) => {
    console.log('Delete: ', id);
  	return state.filter(x => x.id !== id);
  }, state)
  .startWith(state);
}).subscribe(x => { console.log('State:', x); });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.7/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

如果您停止依赖异步管道并使用变量处理您的歌曲,它会变得更容易:

import { filter } from 'rxjs/operators';
export class ArtistComponent implements OnInit {
  private songs: any;

  constructor(
    private route: ActivatedRoute,
    private service: ArtistService
  ) {
    this.getRepertoire().subscribe(songs => this.songs = songs);
  }

  getRepertoire() {
    return this.route.paramMap
      .switchMap((params: ParamMap) =>
        this.service.fetchRepertoire(params.get('id')));
  }

  delete(id): void {
    this.songs = this.songs.filter(song => song.id !== id);
  }
}

这样,您可以简单地过滤,就像它是一个简单的对象数组。

答案 2 :(得分:0)

我建议您在组件上创建新属性,您将在此处存储状态。 (这里了解一系列歌曲)。

总是更好地概念化您的代码,代表您的州(或商店)的内部属性以及具有同步应用程序其余部分的角色的另一个属性(通过observable / event)。

另一个提示是按模型强类型化您的代码。将更容易调试和维护。

然后你只需要根据你的逻辑更新它,然后在主题

上更新
export interface SongModel {
        id: number;
        title: string;
        artiste: string;
    }

    export class ArtistComponent implements OnInit {
        private repertoire$ : Observable<SongModel[]>;
        private repertoireSubject: BehaviorSubject<SongModel[]>;
        //Array of song, should be same type than repertoireSubject.
        private songs: SongModel[];

        constructor(
            private route: ActivatedRoute,
            private service: ArtistService
        ) {

            //We push all actual references.
            this.getRepertoire().subscribe(
                songs => {
                    this.songs = songs;
                    this.repertoireSubject.next(this.songs);
                }
            );
        }

        ngOnInit() {
            //Because is suject of array, you should init by empty array.
            this.repertoireSubject = new BehaviorSubject<SongModel[]>([]);
            this.repertoire$ = this.repertoireSubject.asObservable();
        }


        getRepertoire() {
            return this.route.paramMap
                .switchMap((params: ParamMap) =>
                this.service.fetchRepertoire(params.get('id')));
        }

        //THIS IS WHERE I'M HAVING TROUBLE
        delete(id: number): void {
            // Update your array referencial.
            this.songs = this.songs.filter(songs => songs.id !== id);
            // Notify rest of your application.
            this.repertoireSubject.next(this.songs);
        }
    }