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



我为我的一个项目使用 angular 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()
}

但这也是,我看到网络选项卡中有多个请求而不是一个。必须做什么才能只拨打一个电话并与所有订阅者共享结果?请帮忙。

我的第一个建议是考虑按照这些思路对代码进行一些简化

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是否不为 null 以及它是否具有一些元素。但是您可以使用任何其他逻辑,可能取决于输入参数。

另一个故事是同时发出 2 个呼叫的问题。在这种情况下,你可能希望既share可观察量,以便只共享一个订阅,又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操作员执行。它的共享部分确保订阅是共享的。它的重播部分(缓冲区大小为 1)确保始终返回存储的最后一个结果。

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

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

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

最新更新