Meteor 如何将mergeMap内部订阅限制为N最新或滑动窗口队列
我有一个从两个流合并而来的源流。当源流发出事件时,我想调用订阅函数Meteor 如何将mergeMap内部订阅限制为N最新或滑动窗口队列,meteor,pagination,rxjs,subscription,mergemap,Meteor,Pagination,Rxjs,Subscription,Mergemap,我有一个从两个流合并而来的源流。当源流发出事件时,我想调用订阅函数Meteor.subscribe并保持其打开状态,因此我使用mergeMap。当订阅准备就绪时,我将管道传输到另一个mergeMap,以填充数据。它工作得很好,直到我点击100次,内存消耗急剧上升。问题是,如何将mergeMap限制在前N个订阅,而不是通过concurrent:Number,而是最近N个订阅,就像滑动窗口一样 函数paginationCache$():可观察{ 返回合并(this.pageParamsChanged
Meteor.subscribe
并保持其打开状态,因此我使用mergeMap
。当订阅准备就绪时,我将管道传输到另一个mergeMap
,以填充数据。它工作得很好,直到我点击100次,内存消耗急剧上升。问题是,如何将mergeMap限制在前N个订阅,而不是通过concurrent:Number
,而是最近N个订阅,就像滑动窗口一样
函数paginationCache$():可观察{
返回合并(this.pageParamsChanged$,this.routerParamsChanged$)
.烟斗(
合并映射((新参数)=>{
//第一个合并映射订阅数据,第二个合并映射取消订阅时取消订阅
返回可观察的。创建((观察者:订阅者)=>{
让subscription=Meteor.subscripte('my/best/data/sub',newParams,
() => {
观察员:下一个(订阅);
observer.complete();
});
});
}),
合并地图((订阅:任意)=>{
//第二个订阅只是填充数据
返回可观察的。创建((观察者:订阅者)=>{
const collection=new Mongo.collection(subscription.collectionName);
const{selector,options}=this.mongoParams();
collection.find(选择器、选项).dataChanges((数据)=>{
observer.next({data});
});
return()=>{
订阅。停止();
};
});
})
);
}
我想更详细地解释一下代码中发生了什么
在我的示例中,source流(管道之前的merge
)只要我在web界面中单击按钮,它就永远不会完成,因此当我在界面中单击next或previous按钮时,它会发出更改FirstmergeMap
从源流获取更改并将其发送到后端API(后端API也有冲突的命名发布/订阅)。因此,当客户端上的数据可用时,我会调用observer.next(subscription)
移动到第二个mergeMap
,但我无法销毁或停止meteor的订阅。原因有二:一,。我想获得对所选数据的实时更改,2。如果我停止meteor的订阅,客户端的数据将被删除。因此,现在secondmergeMap
如果所选数据在服务器上更新,它将持续更新所选数据
因此,在每个UI按钮单击(下一步、上一步)之后,我就有了新的订阅链。如果原始数据表不太大(1000条记录),我只点击了几次,这是正常的。但是,我可以有超过30000个,我可以点击我的按钮很多次
所以,我们的想法是使mergeMap像一个有限大小的队列,只容纳最后N个订阅,但在我单击按钮时,队列一直在变化
上次编辑:工作代码:
函数paginationCache$():可观察{
常数N=3;
const subscriptionsubject=新主题();
返回合并(this.pageParamsChanged$,this.routerParamsChanged$)
.烟斗(
合并映射((新参数)=>{
//第一个合并映射订阅数据,第二个合并映射取消订阅时取消订阅
subscriptionsubject.next();
返回可观察的。创建((观察者:订阅者)=>{
让subscription=Meteor.subscripte('mu/best/data/sub',newParams,
() => {
观察员:下一个(订阅);
observer.complete();
});
});
}),
合并地图((订阅:任意)=>{
//第二个订阅只是填充数据
返回可观察的。创建((观察者:订阅者)=>{
const collection=new Mongo.collection(subscription.collectionName);
const{selector,options}=this.mongoParams();
collection.find(选择器、选项).dataChanges((数据)=>{
observer.next({data});
});
return()=>{
订阅。停止();
};
}).烟斗(
takeUntil(订阅主题)
.烟斗(
以(N)为例,
过滤器(((ux,idx)=>idx==N-1)
)
)
);
})
);
}
在不考虑您的代码片段的情况下,以下是我的做法:
不是按concurrent:Number发送到前N个订阅,而是发送到最近的N个订阅,就像滑动窗口一样
如果我理解正确,您可能会想要这样的东西(假设N=3
):
如果是这样的话,我可以这样解决:
const subscriptionsubject=new Subject();
src$管道(
合并地图(
data=>(新的可观察对象(s=>{/*…*/subscriptionsubject.next(null)/*在出现新订阅时通知它*/}))
.烟斗(
武田(
subscriptionsSubject.pipe(
以(N)为例,//订阅'N'之后,它将完成
filter((\ux,idx)=>idx==N-1)//不希望立即完成,但仅在达到'N'个订阅时完成
)
)
)
)
)
我有两个想法:
N = 3
Crt | 1 | 2 | 3 |
Subscriptions | S1 | S2 | S3 |
When Crt = 4
Crt | 2 | 3 | 4 |
Subscriptions | S2 | S3 | S4 |
return () => {
subscription.stop();
observer.complete();
};
import { of, range } from 'rxjs';
import { map, bufferCount, switchMap, shareReplay, tap } from 'rxjs/operators';
range(10)
.pipe(
// turn each value to an Observable
// `refCount` is used so that when `switchMap` switches to a new window
// it won't trigger resubscribe to its sources and make more requests.
map(v => of(v).pipe(shareReplay({ refCount: false, bufferSize: 1 }))),
bufferCount(3, 1),
tap(console.log), // for debugging purposes only
switchMap(sourcesArray => merge(...sourcesArray)),
)
.subscribe(console.log);