使用forkjoin合并HTTP可观察对象

29

我正在尝试使用forkjoin来避免嵌套的可观察对象。当前(嵌套)版本如下:

  this.http.get('https://testdb1.firebaseio.com/.json').map(res => res.json()).subscribe(data_changes => {
    this.http.get('https://testdb2.firebaseio.com/.json').map(res => res.json()).subscribe(data_all => {
      /* Do this once resolved */
      this.platform.ready().then(() => {
        this.storage.set('data_changes', data_changes);
        this.storage.set('data_all', data_all);
        document.getElementById("chart").innerHTML = "";
        this.createChart();
      });
    });
  },

    err => {
      this.platform.ready().then(() => {
        console.log("server error 2");
        document.getElementById("chart").innerHTML = "";
        this.createChart();
      });
    });
  }

我可以将第一部分改写为:

Observable.forkJoin(
  this.http.get('https://testdb1.firebaseio.com/.json').map((res: Response) => res.json()),
  this.http.get('https://testdb2.firebaseio.com/.json').map((res: Response) => res.json())
)

但我不确定如何添加.subscribe方法来同时访问data_changesdata_all

看另一个例子,我知道它应该长这样.subscribe(res => this.combined = {friends:res[0].friends, customer:res[1]});,但我不确定如何将其适应到我的例子中。

1个回答

47

请尝试使用combineLatest而不是forkJoin

使用combineLatest

const combined = Observable.combineLatest(
  this.http.get('https://testdb1.firebaseio.com/.json').map((res: Response) => res.json()),
  this.http.get('https://testdb2.firebaseio.com/.json').map((res: Response) => res.json())
)

combined.subscribe(latestValues => {
    const [ data_changes , data_all ] = latestValues;
    console.log( "data_changes" , data_changes);
    console.log( "data_all" , data_all);
});

您也可以使用 forkJoin 进行处理,但是 forkJoin 会在所有调用完成并返回结果时返回数据,而在 combineLatest 中,当任何一个可观察对象发出一个值时,它将发出每个对象的最新值。

使用 forkJoin

const combined = Observable.forkJoin(
  this.http.get('https://testdb1.firebaseio.com/.json').map((res: Response) => res.json()),
  this.http.get('https://testdb2.firebaseio.com/.json').map((res: Response) => res.json())
)

combined.subscribe(latestValues => {
    const [ data_changes , data_all ] = latestValues;
    console.log( "data_changes" , data_changes);
    console.log( "data_all" , data_all);
});

同时调用两个函数并检查控制台日志,你就会有思路了。


2
如果回答中包含为什么OP应该更喜欢使用combineLatest的解释,那么这将是一个更好的答案。 - cartant
如果您发现这个有用,请接受答案。 - Vivek Doshi
7
您对 combineLatest 行为的描述是不正确的。它不会发出任何内容,直到它传递的每个可观测对象至少发出一次。而 HTTP 可观测对象只会发出一次,那么使用它与使用 forkJoin 有什么区别呢? - cartant
是的,我知道,我觉得我没有解释清楚。 - Vivek Doshi
1
顺便提一下,forkJoin 只会在调用 forkJoin 后观察到新值时触发,因此如果其中一个可观察对象已经返回了一个值,则 forkJoin 将永远不会触发下一个。即使可观察对象已经发出了它的值,combineLatest 也会触发。如果有人遇到订阅 next 函数从未被调用的情况,这可能会对他们有所帮助。 - Chris Putnam
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接