反应性地链接请求

时间:2017-11-20 09:14:53

标签: angular rxjs reactive-programming

我是反应式编程的新手,并且陷入了一个可能简单的问题。 我有两个方法返回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的所有尝试都是一样的。

2 个答案:

答案 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)

与您的问题相关的两条一般规则:

  1. 如果可以避免,请不要手动使用订阅,在您的情况下最有可能避免使用订阅。

  2. 避免像这样的客户端计算,因为发送多个REST调用(假设你正在做)在连接和服务器上非常沉重,并且通常需要更长时间,因为有一个限制可以完成多少个并行请求。 - 所以我强烈建议为这样的事情实现一个单独的端点。

  3. 话虽如此,这就是我写这个流的方式

    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));
    }
    
相关问题