不要使用publishReplay缓存错误

时间:2017-05-19 01:36:07

标签: javascript caching rxjs

我有一些Javascript代码:

public browse = (): Observable<IAttribute[]> => {
    if (!this.attributes) {
       this.attributes = Observable
            .defer(() => this.http.browse())
            // cache 1min
            .publishReplay(1, 60000)
            .refCount()
            .take(1);
    }
    return this.attributes;
}

我遇到的一个问题是错误似乎被缓存了。具体情况是用户的会话超时,因此端点返回401,因此用户被重定向到登录页面 - 但因为它在上一次请求的1分钟内尝试转到属性页面重新抛出401而不是让请求新鲜。

有没有办法设置它以便重试错误,但仅在请求缓存版本时?即我不想要返回401的原始请求重试,但第二个请求应该重试请求。

2 个答案:

答案 0 :(得分:1)

在发布重播之前添加catch(Observable.empty())

答案 1 :(得分:1)

所以您仍然需要在原始订阅者中获得错误吗?

这不是那么美丽,有人可能会做得更好。这可能是RxFiddle最糟糕的演示(有一些关于主题的错误),但我仍然分享它......

我们走了,view this on RxFiddle:

let tries = 0
let httpMock = new Rx.Observable(o => {
  if (tries == 0) {
    setTimeout(() => o.error(new Error()), 10)
  } else {
    setTimeout(() => o.next("value"), 10)
  }
  tries++
})

let replaySubject = null
function browse() {
  return Rx.Observable
    .defer(() => httpMock)
    .do(false, (e) => replaySubject = null)
    .multicast(() =>
      replaySubject || (replaySubject = new Rx.ReplaySubject(1)), 
      cache => cache.take(1)
    )
    .let(obs => replaySubject ? replaySubject : obs)
}

browse().subscribe(console.log, console.warn)

setTimeout(() => {
  browse().subscribe(console.log, console.warn)
}, 1000)