失败后重试forkjoin调用

时间:2019-11-12 23:15:54

标签: javascript angular rxjs

我需要来自数组中每个服务的数据才能在forkjoin调用结束时返回,因此,如果失败了,我需要它再次尝试调用。

在下面的示例中,假设requests数组中的三个项目之一失败了。

request(): Observable<T> {
    const requests = [
      this.getService$.getOne(),
      this.getService$.getTwo(),
      this.getService$.getThree()
    ]

    return forkJoin(requests).pipe(
      map(res => this.formatFunc(res))
    );
  }

代码应该是什么样子,以便在调用this.request()时,即使其中一个服务失败并且必须再次获取数据,我仍然可以从所有三个服务中获取数据?

我进行了一些挖掘,发现人们正在添加this.getService$.getOne().catch(e => of([])) ...但这似乎只返回任何内容,而不是再次拨打电话。

我还使用retry

看到过类似的内容
forkJoin(requests).pipe(
      retry(3),
      map(res => this.formatFunc(res))
    )

但是会重试所有三个呼叫还是失败的一个?

3 个答案:

答案 0 :(得分:2)

重试单个请求

const { forkJoin, of, throwError } = rxjs;
const { retry, tap } = rxjs.operators;

let retryCount = 0;

const requests = [
  of(1),
  of(2),
  throwError('thrown error').pipe(
    tap(
      val => { console.log(val); },
      error => {
        console.log(retryCount ? `Retry ${retryCount}:` : 'First:', error);
        retryCount++;
      }
    )
  )
];

forkJoin(requests.map(request => request.pipe(retry(3)))).subscribe(
  val => { console.log(val); },
  error => { console.log('Sub:', error); }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>

答案 1 :(得分:1)

使用mergemap

处理forkjoin
import { of,forkJoin,throwError, } from 'rxjs';
import { retry,tap,mergeMap} from 'rxjs/operators';

let r1=of([1,2,3]).pipe(tap(()=>console.log("r1 called ..."))),
    r2=of([4,5,6]).pipe(tap(()=>console.log("r2 called ..."))),
    r3=of([7,8,9]).pipe(tap(()=>console.log("r3 called ...")));

of({})
.pipe(
  mergeMap(
    ()=>forkJoin(r1,r2,r3,throwError("some error"))
  ),
  tap({
    next:()=>{
      console.log("next...")
    },
    error:()=>{
      console.log("error..");
    }
  }),
 retry(3)
).subscribe();

这应该控制台error 4次。

这是与游乐场rxjs playground

的链接

答案 2 :(得分:1)

但是,以上答案具有无效的错误处理,这种想法是正确的:您必须分开处理每个请求的错误。应该执行以下操作:

forkJoin([
request1.pipe(retryWhen(genericRetryStrategy())),
request2.pipe(retryWhen(genericRetryStrategy()))
])

示例中提到的genericRetryStrategy可以从此处获取(作为示例):https://www.learnrxjs.io/operators/error_handling/retrywhen.html示例2:持续时间增加的可自定义重试。

您可以提供所需的任何其他逻辑代替