首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待RxJs.Subscriptions完成后再继续

等待RxJs.Subscriptions完成后再继续
EN

Stack Overflow用户
提问于 2017-02-09 08:27:36
回答 2查看 22.4K关注 0票数 16

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

代码语言:javascript
复制
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();})
  }
}

我的组件看起来像这样:

代码语言:javascript
复制
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的方法,但在本例中我没有这些方法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-09 12:22:45

好的,你想要的东西可以通过这个来实现:

代码语言:javascript
复制
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);
    }
}

这是对您的代码的修改。正如您所看到的,不需要订阅服务组件中的可观察对象。甚至不需要在服务组件之外单独订阅它们。我们只需以某种方式组合可观测对象,就可以在单个最终的订阅()中直接获得最终结果。

更新

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

稍微简化一下(跳过热门的可观察对象),直到您订阅了可观察管道,它才会开始执行任何操作。do()只是众多运算符中的一个,这些运算符被设计为在可观察对象链中产生一些“副作用”,例如,它可以在可观察管道的中间输出一些中间结果,以供调试之用。这是主要的区别。因此,您可以在没有do()的情况下在subscribe()中获得某些内容,但是如果没有subscribe(),则在do()中不会获得任何内容。

票数 8
EN

Stack Overflow用户

发布于 2018-02-13 13:35:54

通过将订阅移动到组件,使用Observable.forkJoin可以轻松解决您的问题。它需要一个冷可观察数组,在订阅之后,您将收到一个结果数组。如下所示:

代码语言:javascript
复制
Observable.forkJoin([ 
    a.get(),
    b.get()
]).subscribe(
    results => {
        doSomething(results[0], results[1]);
    },
    err => {
        //handle error
    }
);

直到两个请求都进入,订阅中的回调才会被调用。

如果a.get()b.get()失败,将调用error方法

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42126153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档