Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Meteor 如何将mergeMap内部订阅限制为N最新或滑动窗口队列_Meteor_Pagination_Rxjs_Subscription_Mergemap - Fatal编程技术网

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按钮时,它会发出更改First
mergeMap
从源流获取更改并将其发送到后端API(后端API也有冲突的命名发布/订阅)。因此,当客户端上的数据可用时,我会调用
observer.next(subscription)
移动到第二个
mergeMap
,但我无法销毁或停止meteor的订阅。原因有二:一,。我想获得对所选数据的实时更改,2。如果我停止meteor的订阅,客户端的数据将被删除。因此,现在second
mergeMap
如果所选数据在服务器上更新,它将持续更新所选数据

因此,在每个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'个订阅时完成
)
)
)
)
)
我有两个想法:

  • 你没有完成第二个内部观察。我想这不应该是你的问题的根源,但如果你是c,最好完成观察者
    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);