我正在使用publishReplay(1).refCount()来缓存Angular5中的http请求。这很好 - 除了错误情况。
我正在吞咽并报告来自http源的异常,这就是我在下面的代码中传递Observable.of(undefined)的原因。在这种情况下,它当然会缓存未定义 - 但是跟随订阅者不应该获得该值,而是应该再次请求http资源,就像没有缓存一样。
我目前的代码:
result: Observable<any>;
list() {
if (this.result === undefined) {
this.result = this.http.get(`https://swapi.co/api/people`)
.catch(error => {
console.error("Something really bad happened", error);
return Observable.of(undefined);
// in that case, reset publishReplay
})
.publishReplay(1)
.refCount();
}
return this.result;
}
我有一个stackblitz(使用shareReplay,但同样的问题)来显示行为:https://stackblitz.com/edit/angular-s5zuqa。 单击“加载”应该重新请求http源,而不是从catch中提供缓存的对象。
答案 0 :(得分:3)
所以,如果我理解正确,你就是在寻找这个,对吧?这里有两件重要的事情需要注意:
shareReplay(1)
代替publishReplay(1).refCount()
。catch
已移至后面的多播运营商。你第一次看到(伪造的)HTTP调用错误,发出undefined
(因为我们抓住它)。下一次,我们再次运行请求,这次获得第三次运行缓存的结果(42),不会导致另一个请求。
// Just to keep track of how often we sent the request already
let counter = 1;
// A fake HTTP request which errors the first time, then succeeds
const request$ = Rx.Observable.of(null)
.do(() => console.log('HTTP Request (#' + counter + ')!'))
.delay(250)
.switchMap(() => counter++ === 1
? Rx.Observable.throw('Error!')
: Rx.Observable.of(42)
);
// =========
const result$ = request$
.shareReplay(1)
.catch(() => Rx.Observable.of(undefined))
;
Rx.Observable.timer(0, 1000)
.take(3)
.do(() => console.log('Subscribing to result$…'))
.switchMap(() => result$)
.subscribe(value => console.log('Received value: ', value));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>
&#13;
答案 1 :(得分:0)
请谨慎使用 TIMESTAMP_FORMAT('2017-03-01 14:26:02.646171', 'YYYY-MM-DD HH24:MI:SS.NNNNNN')
。取消订阅和引用计数会带来一些麻烦。
新的配置参数已添加到shareReplay(1)
中,以解决此问题。
此问题在这里得到了更好的解释:
https://github.com/ReactiveX/rxjs/issues/3336
到目前为止,新功能即将推出,但尚未发布。