一个可观察的,多个订阅者Rxjs / Angular共享不起作用

时间:2018-05-07 12:30:48

标签: javascript angular rxjs angular4-httpclient

我为我的一个项目使用角度4,我正在进行http调用以获取数据。我从后端返回数据时缓存数据,这样对于后续请求,我就不必一次又一次地进行其余的调用。

getApplication(): Observable<Array<Application>> {
        return new Observable<Array<Application>>((observer) => {
            if (this.app&& this.app.length > 0) {
                observer.next(this.app)
            } else {
                this._http
                    .get<Application[]>(this.url)
                    .map((app) => this.mapToApp(app))
                    .subscribe((result: Array<Application>) => {
                        observer.next(result);
                    }, () => {
                        observer.next([]);
                    })
            }
        })
    }

这完全没问题。但是,如果两个呼叫同时进行,我看到网络选项卡中有两个请求而不是一个。所以我尝试使用share()来满足'一个可观察的,多个订户'。

getApplication(): Observable<Array<Application>> {
            return new Observable<Array<Application>>((observer) => {
                if (this.app&& this.app.length > 0) {
                    observer.next(this.app)
                } else {
                    this._http
                        .get<Application[]>(this.url)
                        .map((app) => this.mapToApp(app))
                        .subscribe((result: Array<Application>) => {
                            observer.next(result);
                        }, () => {
                            observer.next([]);
                        })
                }
            }).share()
        }

但是,我也看到网络标签中有多个请求而不是一个。只需拨打一个电话并与所有订户共享结果需要做些什么?请帮忙。

2 个答案:

答案 0 :(得分:2)

我的第一个建议是考虑在这些行中的代码中进行一些简化

getApplication(): Observable<Array<Application>> {
      if (this.app && this.app.length > 0) {
         return Observable.of(this.app);
      }
      return this._http
                    .get<Application[]>(this.url)
                    .map((app) => this.mapToApp(app))
                    .do((result: Array<Application>) => {
                        this.app = result;
                    }
}

使用此逻辑,您可以使用所需的任何逻辑进行缓存。您已决定检查this.app是否为空,以及是否包含某些元素。但是你可以使用任何其他逻辑,可能取决于输入参数。

另一个故事是同时发出2个电话的问题。在这种情况下,您可能希望两者都share Observable,以便只共享一个订阅并记录最后一个结果replay,以便您可以返回缓存的值。

执行此操作的一种方法可能是以下

private cache$: Observable<Array<Application>>;

requestApplication(): Observable<Array<Application>> {
          return this._http
                        .get<Application[]>(this.url)
                        .map((app) => this.mapToApp(app))
                        .do((result: Array<Application>) => {
                            this.app = result;
                        }
}

getApplication() {
    if(!cache$) {
       cache$ = this.requestApplication().shareReplay(1);
    }
    return cache$;
}

此处的技巧由shareReplay运算符执行。 share 部分确保共享订阅。缓冲区大小为1的重放部分确保始终返回存储的最后结果。

然后您可能会遇到偶尔清除缓存的问题。但是这里的故事变得更加复杂,我建议你看看这篇非常好的文章https://blog.thoughtram.io/angular/2018/03/05/advanced-caching-with-rxjs.html

答案 1 :(得分:0)

你是否两次调用getApplication()方法?如果是,那么您创建两个不同的可观察量。

也许您应该使用主题来关注发布者/订阅者模式?