我有一个使用Subject和Observable设置的歌曲列表(在视图中显示为| async
),现在我想从列表中删除一首歌,执行一些filter()
并调用{{1在主题上。
我如何以及在何处过滤?现在我正在对主题进行next()
并将其传递给getValue()
,以及主题。这似乎是错误的和循环的。
我也尝试订阅主题并以这种方式获取数据,过滤它并在next()
内调用next()
,但我得到了一个RangeError。
我可以通过存储所有已删除的ID来过滤Observable。然后,通过在那里删除歌曲,主题的列表变得不同步,并且每个观察者都必须具有看似荒谬的已删除id的列表。我的老人和精神都快速增长。请帮我上网:(
subscribe()
答案 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;
或类似的东西:
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;
答案 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);
}
}