在恢复

时间:2017-02-09 00:27:36

标签: angular rxjs

在我的Angular 2应用程序中,我需要发出一系列http请求。我有两项服务,A& B,每个请求,A.get()B.get(),从API获取数据并将其存储在他们的服务中。这两个可以同时调用,但我有第三个请求doSomething()取决于A.get()B.get()的结果。由于A.get()B.get()都在本地存储其响应,因此返回值最终为RxJs订阅。像这样:

class A{
  public data;
  public get(){
    return api.call(params).subscribe((response)=>{ this.data = response.json();})
  }
}

class B{
  public data;
  public get(){
    return api.call(params).subscribe((response)=>{ this.data = response.json();})
  }
}

我的组件看起来像这样:

class MyComponent{
  constructor(private a: A, private b: B){
    a.get();
    b.get();
    this.doSomething(a.data, b.data);
  }
  doSomething(aData, bData){
    ...
  }
}

我的问题是doSomething()失败,因为a.get()b.get()已经完成了http请求。我需要一种方法来暂停调用doSomething(),直到我的其他呼叫完成。我一直在搜索但是没有运气这个问题。 RxJs文档提供了一些可以合并Observables的方法,但这不是我在这种情况下的方法。

2 个答案:

答案 0 :(得分:7)

嗯,你想要的就是这个:

class A {

    private data;

    public get(): Observable<any> {
        // this is a very primitive caching just to show concept
        if (this.data) {
            return Observable.of(this.data);
        }
        // In real life it would be something like this:
        //  let call = this.http.get(...).map(r => r.json())
        let call = Observable.of("some value A");
        return call.do(s => this.data = s);
    }

}

class B {

    private data;

    public get(): Observable<any> {
        if (this.data) {
            return Observable.of(this.data);
        }
        let call = Observable.of("some value B");
        return call.do(s => this.data = s);
    }

}

class MyComponent {
    constructor(private a: A, private b: B) {
        Observable
            .zip(this.a.get(), this.b.get(), (a: any, b: any) => { return { a: a, b: b } })
            .subscribe((r) => {
                this.doSomething(r.a, r.b);
            });
    }
    doSomething(aData, bData) {
        console.log("aData", aData);
        console.log("bData", bData);
    }
}

这是对代码的修改。如您所见,无需在服务组件内订阅observable。甚至不需要在服务组件之外单独订阅它们。我们可以通过以某种方式组合observable来直接在单个最终订阅()中获得最终结果。

<强>更新

do()和subscribe()之间有什么区别。

简化一点(跳过热的observable),可观察的管道在你订阅之前不会开始做任何事情。 do()只是众多运营商中的一个,旨在产生一些副作用。在您的observable链中,例如它可以在可观察管道中间输出一些中间结果到控制台以进行调试。这是主要的区别。所以,你可以在subscribe()中获得一些东西而不用do(),但是如果没有subscribe()你就不会得到do()。

答案 1 :(得分:2)

通过将订阅移至组件,使用Observable.forkJoin轻松解决您的问题。它需要一组冷可观察量,在订阅后,您会收到一系列结果。像这样:

Observable.forkJoin([ 
    a.get(),
    b.get()
]).subscribe(
    results => {
        doSomething(results[0], results[1]);
    },
    err => {
        //handle error
    }
);

两个请求进入之前,不会调用订阅中的回调。

如果a.get()b.get()失败,则会调用错误方法