我是反应式编程的新手,并且陷入了一个可能简单的问题。 我有两个方法返回observables。
GetQueues(): Observable<Queue[]>{...}
和
GetMessageCount(queue: Queue): Observable<number>{...}
现在我想在带有以下签名的方法中链接这些
GetAllQueueMessageCount(): Observable<number>{...}
你可以想象,我想调用第一个方法来读取队列列表,迭代结果并为每个队列调用第二个方法。
我可以想象下面的内容,但正如您所见,这并不能返回签名所期望的内容:
public GetAllQueueMessageCount(): Observable<number> {
var messageCount = 0;
this.GetQueues()
.subscribe(queues => {
var queueCountRequests = [];
queues.forEach((queue) => {
queueCountRequests.push(this.GetQueueMessageCount(queue));
});
Observable.forkJoin(queueCountRequests)
.subscribe(t => {
t.forEach(
count => messageCount = messageCount + (count as number));
});
}, error => Observable.throw(error));
}
我使用flatMap的所有尝试都是一样的。
答案 0 :(得分:2)
我认为这是您正在寻找的结构。
由于您返回了一个可观察的一般规则,因此使用map()
或其形式(例如flatMap()
而不是subscribe()
),并在每个级别使用返回值。
const GetAllQueueMessageCount(): Observable<number> {
return this.GetQueues()
.map(queues => {
const queueCountRequests = queues
.map(queue => this.GetQueueMessageCount(workflowId, queue.Name) );
return Observable.forkJoin(queueCountRequests)
.map(
results: number[] => results.reduce((sum,num) => sum + num, 0))
error => Observable.throw(error)
)
}
答案 1 :(得分:1)
与您的问题相关的两条一般规则:
如果可以避免,请不要手动使用订阅,在您的情况下最有可能避免使用订阅。
避免像这样的客户端计算,因为发送多个REST调用(假设你正在做)在连接和服务器上非常沉重,并且通常需要更长时间,因为有一个限制可以完成多少个并行请求。 - 所以我强烈建议为这样的事情实现一个单独的端点。
话虽如此,这就是我写这个流的方式
public GetAllQueueMessageCount(): Observable<number> {
return this.GetQueues()
.mergeAll() // split up the array into seperate emissions
.concatMap(queue => this.GetQueueMessageCount(workflowId, queue.Name))
.toArray() // optional if you want one single result-emit use it, if you want a new emission for every queueMessageCount, remove it
.map(msgCounts => msgCounts.reduce((sum,num) => sum + num, 0));
}