在RxJS管道中处理未知数量的观测值

在RxJS管道中处理未知数量的观测值,rxjs,subject-observer,Rxjs,Subject Observer,我对我的服务器进行了数千次调用,但为了避免过载,我对RxJS设置了10次并发限制: const calls=新主题(); 水管( 合并所有(10) ).subscribe(); while(int{ //在这里呼叫服务器 })) } 问题是我不知道会打多少个电话,我需要知道工作何时完成。一种方法是在队列中没有任何东西保留5秒钟左右时获取 我该怎么做?在阅读了您的评论之后,我认为答案在于一旦我们知道没有更多的数据可从数据库读取,就对主题发出complete命令 这是一种伪代码,这可能是解决方案的

我对我的服务器进行了数千次调用,但为了避免过载,我对RxJS设置了10次并发限制:

const calls=新主题();
水管(
合并所有(10)
).subscribe();
while(int<未知值){
调用。下一个(新的可观察对象((观察者)=>{
//在这里呼叫服务器
}))
}
问题是我不知道会打多少个电话,我需要知道工作何时完成。一种方法是在队列中没有任何东西保留5秒钟左右时获取


我该怎么做?

在阅读了您的评论之后,我认为答案在于一旦我们知道没有更多的数据可从数据库读取,就对
主题发出
complete
命令

这是一种伪代码,这可能是解决方案的草稿

// callToServer is a function that calls the server and returns an Observable
const callToServer: Observable<any> = (input) => httpClient.post(url, input);

const calls = new Subject<any>();
calls.pipe(
    // margeMap allows to set concurrency level as second parameter
    mergeMap(input => callToServer(input), 10)
).subscribe(
   {
      next: response => {
        // do something with the response
      },
      error: err => {
        // manage error occurrences
      },
      complete: () => {
        // here you come when the Subject completes
      }
   }
);

const cursor = db.readFromMyTable();

while(cursor has still data){
    const data = cursor.getNext(100);
    // for each record issue a next against the calls Subject
    data.forEach(d => calls.next(d));
}

// when there are no more records completes the calls Subject
//callToServer是一个调用服务器并返回可观察值的函数
const callToServer:Observable=(输入)=>httpClient.post(url,输入);
const calls=新主题();
水管(
//margeMap允许将并发级别设置为第二个参数
合并映射(输入=>callToServer(输入),10)
).订阅(
{
下一步:响应=>{
//对回应做点什么
},
错误:err=>{
//管理错误发生
},
完成:()=>{
//当主题完成时,你就来了
}
}
);
const cursor=db.readFromMyTable();
while(光标仍有数据){
const data=cursor.getNext(100);
//对于每个记录,针对calls主题发布下一个记录
data.forEach(d=>calls.next(d));
}
//当没有更多记录时,完成呼叫主题

在我阅读了您对流程的评论后,我认为您不需要合并映射,因为每个新请求都将在前一个请求完成后进行,因此我将建议以下方法

let{
属于
主题
}=rxjs;
让{
开关图,
延迟
扫描
}=rxjs.运算符;
常数db=[1,2,3,4,5,6,7];
const requester=新主题();
const mockRequest=({page,items})=>
共(分贝切片(第*页项目,(第+1页)*项))。管道(延迟(500));
每页的常数项=2;
请求者
.烟斗(
switchMap(pageData=>mockRequest(pageData)),
扫描(
(acc,x)=>{
常数newIdx=+acc[0]+1;
返回[newIdx,x];
},
[0, []]
)
)
.订阅(([i,x])=>{
如果(x.length!==0){
下一步({page:i,items:items\u PER\u page});
控制台日志(x);
}否则{
console.log(“完成并准备取消订阅”);
}
});
next({page:0,items:items\u PER\u page})

您不需要创建自己的流,只需:

从一个将调用一次的主题开始:

const call$ = new BehaviorSubject(0);

call$.pipe(
    concatMap(call => {
        return callYourDatabase(call); // Pagination or whatever
    }),
    tap(res => {
        if (res) {
            call$.next(db); // Call again after completion if the previous has values
        }
    })
)

你从哪里开始?您是否有一个数组,并且需要进行与数组元素相同数量的调用?您是否从一个流开始,并对流通知的每个项目进行调用?我首先调用数据库以获取前100个元素。我再次调用数据库以获取接下来的100个元素,直到数据库中没有更多的元素。我在得到100个元素后添加这些调用,并继续以100个为一批添加,直到没有更多的元素。希望这是清楚的…:)这里没有并发性。。。