RxJS-将发出的值映射到多个Http请求的组合输出

时间:2019-01-18 19:41:15

标签: angular rxjs angular2-observables

我有这样的东西:

// getNums returns of Obsevable<number[]>
nums : Observable<number[]> = getNums();

// requestNum is a server call that takes a number and returns Observable<number>
serverNums : Observable<Observable<number>[]> = x.pipe(
    map(num_array => num_array.map(n => requestNum(n)))
);

// Part of an external API that I don't own.
function requestNum(num : number) : Observable<number> {
  // make a server call
}

问题是serverNums的类型为Observable<Observable<number>[]>。 我需要serverNums才能成为Observable<number[]>,这样我才能做到

this.result = combineLatest(nums, serverNums).pipe(
    [nums : number[], serverNums : number[]] => {
      for (i=0; i<nums.length; i++) {
        console.log(nums[i], serverNums[i]);
      }
    }
);

因为this.result必须在我的构造函数中实例化为Observable<Result[]>类型,而不是在订阅中设置。

所以我不能做subscribe(() => {this.result = result})

2 个答案:

答案 0 :(得分:0)

您没有解释Data接口的结构是什么,所以我可以从数组中假定:

[1,2,3]

您要创建对象:

{1:1, 2:2, 3:3}.

(如果您发布数据界面,我将相应地更新答案)。


要从数组创建对象,可以使用reduce

x.pipe(reduce((pre,curr)=>{pre[curr]=curr; return pre;}, {})

点数以一个空对象({})开头,并在每次迭代中将pre [curr]属性添加到该对象并将其设置为curr。

  • pre 是上次迭代中的上一个值
  • curr 是当前迭代的当前值(在上例中为1、2或3)

编辑:

您需要使用mergeMap(又称flatMap)将Observable<Observable<number>>展平为Observable<number>

serverNums : Observable<Observable<number>[]> = x.pipe(
    map(num_array => num_array.map(n => requestNum(n)),
    mergeMap(num=>num)
)

这将在Observable类型的单个observable中发出requestNum(n)的所有值。

答案 1 :(得分:0)

使用forkJoin执行并合并所有http请求和mergeMap从源发出到forkJoin返回的Observable的数组。 forkJoin将所有HTTP请求中最后(也是唯一)发出的值组合成一个数组。请注意,requestNum必须在发出值forkJoin后才能完成。 (Angular HttpClient发出的Http请求在发出值后完成)

根据可观察的x和所需的行为,可以使用switchMap代替mergeMap

import { forkJoin } from 'rxjs'; 
import { mergeMap } from 'rxjs/operators';

serverNums : Observable<number[]> = x.pipe(
    mergeMap(num_array => forkJoin(num_array.map(n => requestNum(n))))
);