重试内部Observable,

时间:2018-04-11 12:20:58

标签: rxjs

我有一个外在的Observable。内部Obersvable有时会出现错误,可以通过重试来解决。



function sm$(val) {
  if (Math.random() > .4) {
    return Rx.Observable.throw(val)
  } else {
    return Rx.Observable.of(val)
  }
}

function sm(val) {
  return Rx.Observable.of(val)
    .switchMap(sm$)
    .catch(() => Rx.Observable.of(val).delay(1000).switchMap(sm))
}

Rx.Observable
  .interval(500)
  .switchMap(sm)
  .take(5)
  .subscribe(
    val => console.log("val:", val),
    err => console.log("err:", err),
    () => console.log("complete")
  )

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.min.js"></script>
&#13;
&#13;
&#13;

这个日志,即:

val: 1
val: 2
val: 6
val: 10
val: 11
complete

当我在catch块中返回延迟的observable时,它无法正常工作,只会跳过一些值。没有延迟,它按预期工作,但这不是我想要的。我希望延迟反复推迟。

&#13;
&#13;
function sm$(val) {
  if (Math.random() > .4) {
    return Rx.Observable.throw(val)
  } else {
    return Rx.Observable.of(val)
  }
}

function sm(val) {
  return Rx.Observable.of(val)
    .switchMap(sm$)
    .catch(() => Rx.Observable.of(val).switchMap(sm))
    // removed the delay(1000)
}

Rx.Observable
  .interval(500)
  .switchMap(sm)
  .take(5)
  .subscribe(
    val => console.log("val:", val),
    err => console.log("err:", err),
    () => console.log("complete")
  )
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.min.js"></script>
&#13;
&#13;
&#13;

这个日志总是这样,这就是我的期望:

val: 0
val: 1
val: 2
val: 3
val: 4
complete

2 个答案:

答案 0 :(得分:2)

问题是您正在使用Observable.interval(500).switchMap(sm)

特别是您案例中的switchMap。即使您在内部Observable上使用Observable.interval时,源delay(1000)也会继续发光,只是因为switchMap它在1000ms后想要发出时已经取消订阅。

所以看起来您可以使用concatMap代替外部switchMap

&#13;
&#13;
function sm$(val) {
  if (Math.random() > .4) {
    return Rx.Observable.throw(val)
  } else {
    return Rx.Observable.of(val)
  }
}

function sm(val) {
  return Rx.Observable.of(val)
    .switchMap(sm$)
    .catch(() => Rx.Observable.of(val).delay(1000).switchMap(sm))
}

Rx.Observable
  .interval(500)
  .concatMap(sm)
  .take(5)
  .subscribe(
    val => console.log("val:", val),
    err => console.log("err:", err),
    () => console.log("complete")
  )
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我认为这个问题与你使用延迟1000毫秒同时在发出5个事件后完成流的事实有关,每个事件每500毫秒发生一次。

这意味着由于catch块而延迟的延迟发射可以在流完成后到达。

如果你减少延迟,你可能会得到你想要的东西。我还添加了一些日志以获得更好的图片

import {Observable} from 'rxjs';

function sm$(val) {
    if (Math.random() > .4) {
      return Observable.throw(val)
    } else {
      return Observable.of(val)
    }
}

function sm(val) {
    return Observable.of(val)
      .switchMap(sm$)
      .catch(() => {
                        console.log('error', val);
                        return Observable.of(val).delay(10).switchMap(d => sm(d));
                    })
}

Observable
    .interval(500)
    .switchMap(sm)
    .take(5)
    .subscribe(
      val => console.log("val:", val),
      err => console.log("err:", err),
      () => console.log("complete")
    )