[英]RxJS : Filter one observable using another observable
我有一個流來自API響應的數據流,並有另一個流,它發出需要從源流中過濾的值。
@Injectable({
providedIn: 'root'
})
export class SmpService {
private _smp$ = new ReplaySubject(1);
private _deleteSubject = new BehaviorSubject(null);
constructor(private http: HttpClient) {
const allSmp$ = this.loadSmp().pipe(map(list => list.map(item => item.id)));
const delete$ = this._deleteSubject.pipe(map(value => this.filterSmp(value)));
allSmp$
.pipe(
combineLatest(delete$, (notifications, xf) => {
return xf(notifications);
}),
tap(x => console.log('console ', x))
)
.subscribe(this._smp$);
}
loadSmp(): Observable<any> {
const contextPath = 'some_url';
const url = this.uriPrefix + contextPath;
return this.http.get(url).pipe(map((response: any) => response.notifications || []));
}
filterSmp(value) {
return notifications => notifications.filter(notification => value !== notification);
}
deleteSmp(subscribeItem) {
this._deleteSubject.next(subscribeItem);
}
getSmp(): Observable<any> {
return this._smp$.asObservable();
}
}
過濾工作正常。 但是在頁面加載時,我無法在頁面上呈現初始API響應。 當我通過某個動作觸發deleteStream時,我才收到它。
即使沒有觸發deleteStream,我有什么辦法可以得到初始數據嗎?
而不是Subject
使用BehaviorSubject
具有一些默認值。 例如null
。
private _deleteSubject = new BehaviorSubject(null);
BehaviorSubject
將在每次訂閱時發出默認值。
你遇到的主要問題可能是$delete
是一個“冷”可觀察的,直到_deleteSubject
有一個值。 如果你想在_deleteSubject
給出任何值之前填充_smp$
,那么你將需要使用默認值對其進行初始化,如@ m1ch4ls所述。
@Injectable({
providedIn: 'root'
})
export class SmpService {
private _smp$ = new ReplaySubject(1);
private _deleteSubject = new BehaviorSubject(null);
constructor(private http: HttpClient) {
const allSmp$ = this.loadSmp().pipe(map(list => list.map(item => item.id)));
const delete$ = this._deleteSubject.pipe(map(value => value ? this.filterSmp(value) : (notifications => notifications)));
delete$
.pipe(
withLatestFrom(allSmp$, (xf, notifications) => {
return xf(notifications);
}),
tap(x => console.log('console ', x))
)
.subscribe(this._smp$);
}
loadSmp(): Observable<any> {
const contextPath = 'some_url';
const url = this.uriPrefix + contextPath;
return this.http.get(url).pipe(map((response: any) => response.notifications || []));
}
filterSmp(value) {
return (notifications) => notifications.filter(notification => value !== notification);
}
deleteSmp(subscribeItem) {
this._deleteSubject.next(subscribeItem);
}
}
另一種使用另一種方法過濾一個Observable的方法可以是
private _smp$ = new ReplaySubject(1);
private _deleteSubject = new Subject();
constructor(private http: HttpClient) {
const allSmp$ = this.loadSmp().pipe(map(list => list.map(item => item.id)));
const delete$ = this._deleteSubject.pipe(
map(value => (value ? this.filterSmp(value) : notifications => notifications))
);
allSmp$.merge(delete$)
.pipe(
startWith([]),
scan((acc, value) => {
if (typeof value === 'function') {
return [...value(acc)];
}
return [...acc, ...value];
})
)
.subscribe(this._smp$);
}
在此,我們做了以下事情:
BehaviourSubject(null) -> Subject()
combineLatest -> merge
startWith
並scan
以保持持久的內部狀態 瞧,它有效。 但仍在尋找其他更好的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.