【问题标题】:combining results from multiple rxjs observables组合来自多个 rxjs observables 的结果
【发布时间】:2018-08-15 15:40:00
【问题描述】:

我有一个自动完成输入,当用户键入时,它会从多个端点获取数据,例如:

//service call to fetch data and return as single observable
getAutocompleteSuggestions() {
    const subs$ = [
        this.http.get(endpoint1),
        this.http.get(endpoint2),
        this.http.get(endpoint3)
    ];

    return Observable.forkJoin(...subs$);
}

这些端点中的每一个都返回以下形式的数据:

{ data: [], status: xyz }

我想使用 switchmap,因为我只想显示最终调用的结果,并尝试了以下方法:

   this.getAutocompleteSuggestions(query)
          .switchMap(res => {
             return res.data;
           })
          .subscribe((results: any) => {
            this.results = results;
          });

但是 switchmap 中的“res”是一个数组,知道结果如何包含单个数组,其中包含来自任意数量的 observable 响应的数据吗?

【问题讨论】:

  • 这就是 forkJoin 所做的。它将结果组合到一个数组中。也许我不明白你的问题……你能澄清一下吗?
  • forkjoin 产生的结果是一个数组,所以我想展平该数组,对其进行转换(例如通过 map())并取消以前的请求

标签: javascript angular rxjs reactive-programming rxjs5


【解决方案1】:

我不完全明白你想要什么,但我认为就是这样:

$filter: Subject<string> = new Subject(); //I guess we have some value to filter by??

向主题推送一个值:

this.$filter.next(myNewValue);

在构造函数或初始化中:

this.$filter
   .switchMap(filterValue => { //Get the values when filter changes
       subs$ = [
         this.http.get(endpoint1 + filterValue),
         this.http.get(endpoint2 + filterValue),
         this.http.get(endpoint3 + filterValue)
       ];

       return Observable.forkJoin(...subs$);
   })
   .map(results => { //now map you array which contains the results
      let finalResult = [];
      results.forEach(result => {
          finalResult = finalResult.concat(result.data)
      })
      return final;
   })
   .subscribe(); //Do with it what you want

当我们将新值放入主题时,整个流程将再次执行。如果有任何就绪请求,SwitchMap 将取消所有就绪请求。

【讨论】:

  • 有意思,所以forkjoin在switchMap里面?是否可以链接它以便 switchmap 接受我的请求/可观察的响应?
  • @BenTaliadoros 到那时为时已晚,因为switchMap 将无法取消这些可观察对象。
  • 不取消,只发出最后一个结果
  • 我想我可能对链接元素感到困惑,我看到的例子如下: Rx.Observable.of('some_url') .switchMap(url => this.http.get( url)),所以也许我必须制作一个空白的 observable 并将 switchmap 链接到可以调用那里的服务?
  • SwitchMap 可以将可观察到的流从一个值更改为来自另一个流的新值。在那个小例子中:来自新 http 流的响应的字符串。这只会工作一次,因为 Observable.of 永远不会发出多个值。如果您想要另一个结果,您需要再次创建并调用流。在您的问题中,该值来自自动完成。这个值发生了变化,所以我们把它放在一个主题中。 Observable.of 和 subject 之间的区别在于 subject 可以多次发射。由于主题发出多个值,我们使用 switchmap 来取消先前的请求。
【解决方案2】:

我用过类似的东西,到目前为止效果很好:

        let endpoint1 = this.http.get(endpoint1);
        let endpoint2 = this.http.get(endpoint2);
        let endpoint3 = this.http.get(endpoint3);

        forkJoin([endpoint1, endpoint2, endpoint3])
          .subscribe(
            results => {
              const endpoint1Result = results[0].map(data => data);
              const endpoint2Result = results[1].map(data => data);
              const endpoint3Result = results[2].map(data => data);

              this.results = [...endpoint1Result, ...endpoint2Result, ...endpoint3Result];
            },
            error => {
              console.error(error);
            }
          );

显然是一个非常简单的示例,您将能够更好地处理结果以满足您的需求。

【讨论】:

  • 是的,我知道我可以做到这一点,但它不使用 switchMap,不过谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多